diff --git a/src/sfcc/cartridges/int_b2ccrmsync/cartridge/scripts/b2ccrmsync/hooks/ocapi/shop.customer.js b/src/sfcc/cartridges/int_b2ccrmsync/cartridge/scripts/b2ccrmsync/hooks/ocapi/shop.customer.js index 65967ea0..81e6e015 100644 --- a/src/sfcc/cartridges/int_b2ccrmsync/cartridge/scripts/b2ccrmsync/hooks/ocapi/shop.customer.js +++ b/src/sfcc/cartridges/int_b2ccrmsync/cartridge/scripts/b2ccrmsync/hooks/ocapi/shop.customer.js @@ -66,7 +66,7 @@ function afterPATCH(customer, customerRegistration) { * @returns {Status} Returns the status for the OCAPI request */ // eslint-disable-next-line no-unused-vars -function modifyPOSTResponse(customer, customerResponse) { +function modifyGETResponse(customer, customerResponse) { if (!Site.getCurrent().getCustomPreferenceValue('b2ccrm_syncEnhanceOCAPICustomerResponse')) { return new Status(Status.OK); } @@ -85,4 +85,4 @@ function modifyPOSTResponse(customer, customerResponse) { module.exports.afterPOST = afterPOST; module.exports.afterPATCH = afterPATCH; -module.exports.modifyPOSTResponse = modifyPOSTResponse; +module.exports.modifyGETResponse = modifyGETResponse; diff --git a/src/sfcc/cartridges/int_b2ccrmsync/hooks.json b/src/sfcc/cartridges/int_b2ccrmsync/hooks.json index 16f89b92..b525dd2f 100755 --- a/src/sfcc/cartridges/int_b2ccrmsync/hooks.json +++ b/src/sfcc/cartridges/int_b2ccrmsync/hooks.json @@ -33,7 +33,7 @@ "script": "./cartridge/scripts/b2ccrmsync/hooks/ocapi/shop.customer" }, { - "name": "dw.ocapi.shop.customer.auth.modifyPOSTResponse", + "name": "dw.ocapi.shop.customer.modifyGETResponse", "script": "./cartridge/scripts/b2ccrmsync/hooks/ocapi/shop.customer" }, { diff --git a/src/sfdc/base/main/default/classes/B2CHttpRequestHelper.cls b/src/sfdc/base/main/default/classes/B2CHttpRequestHelper.cls index 46276da2..d9db8c1d 100644 --- a/src/sfdc/base/main/default/classes/B2CHttpRequestHelper.cls +++ b/src/sfdc/base/main/default/classes/B2CHttpRequestHelper.cls @@ -53,18 +53,17 @@ public with sharing class B2CHttpRequestHelper { * @param customerId {String} Represents the B2C ClientID used to drive this request * @param clientId {String} Represents the customerId of the customer being authenticated * @param accessToken {String} Represents the B2C Commerce authToken used for this request - * @param expandParameter {String} Represents the value of the "custom_expand" GET parameter that the B2C cartridge is using to enhance the API response * @return HttpRequest Returns an http-object pre-configured shop-api site retrieval request * */ public static HttpRequest getCustomerAuthRequest( - String apiUrl, String siteId, String apiVersion, String customerId, String clientId, String accessToken, String expandParameter + String apiUrl, String siteId, String apiVersion, String customerId, String clientId, String accessToken ) { return getOCAPIShopAPIHttpRequest( apiUrl, siteId, accessToken, clientId, - '/customers/' + customerId + '/auth' + (String.isEmpty(expandParameter) ? '' : '?custom_expand=' + expandParameter), + '/customers/' + customerId + '/auth', apiVersion, 'post', '{"type" : "credentials"}' diff --git a/src/sfdc/base/main/default/classes/B2CIAAuthCustomerClientCredentialsGrant.cls b/src/sfdc/base/main/default/classes/B2CIAAuthCustomerClientCredentialsGrant.cls index 8e9e75fb..bb78a17b 100644 --- a/src/sfdc/base/main/default/classes/B2CIAAuthCustomerClientCredentialsGrant.cls +++ b/src/sfdc/base/main/default/classes/B2CIAAuthCustomerClientCredentialsGrant.cls @@ -37,7 +37,7 @@ public with sharing class B2CIAAuthCustomerClientCredentialsGrant { // Initialize the authentication request HttpRequest req = B2CHttpRequestHelper.getCustomerAuthRequest( - b2creq.domain, b2creq.siteId, b2creq.version, b2creq.customerId, b2creq.clientId, b2creq.token, b2creq.expandParameter + b2creq.domain, b2creq.siteId, b2creq.version, b2creq.customerId, b2creq.clientId, b2creq.token ); // Initialize the http-handler @@ -55,7 +55,6 @@ public with sharing class B2CIAAuthCustomerClientCredentialsGrant { // Check if the statusCode is found in the response and the response was processed successfully if (accessTokenResult.statusCode == 200) { - // Seed the response object with the access token details accessTokenResult.accessToken = res.getHeader('authorization'); @@ -68,22 +67,10 @@ public with sharing class B2CIAAuthCustomerClientCredentialsGrant { accessTokenResult.accessToken = accessTokenResult.accessToken.replace('Bearer ', ''); accessTokenResult.tokenType = 'Bearer'; } - - if (String.isNotEmpty(b2creq.expandParameter)) { - JSONParse responseParsedJSON = new JSONParse(res.getBody()); - accessTokenResult.promotionIds = new List(); - List promotionsList = responseParsedJSON.get('c_active_promotions').asList(); - for (JsonParse promotionItem : promotionsList) { - accessTokenResult.promotionIds.add(promotionItem.getStringValue()); - } - accessTokenResult.totalPromotionsSize = accessTokenResult.promotionIds.size(); - } } else { - // Otherwise, capture the error message accessTokenResult.errorMessage = B2CConstant.ERRORS_OCAPI_ACCESSTOKENNOTPRESENT; accessTokenResult.isError = true; - } // Add the accessToken to the output outputObj.add(accessTokenResult); diff --git a/src/sfdc/base/main/default/classes/B2CIAAuthCustomerInput.cls b/src/sfdc/base/main/default/classes/B2CIAAuthCustomerInput.cls index 0551d805..07b3d97e 100644 --- a/src/sfdc/base/main/default/classes/B2CIAAuthCustomerInput.cls +++ b/src/sfdc/base/main/default/classes/B2CIAAuthCustomerInput.cls @@ -29,7 +29,4 @@ public with sharing class B2CIAAuthCustomerInput { @AuraEnabled @InvocableVariable(Required=true) public String version; - - @AuraEnabled @InvocableVariable(Required=false) - public String expandParameter; } diff --git a/src/sfdc/base/main/default/classes/B2CIACustomerResolution_TestHelper.cls b/src/sfdc/base/main/default/classes/B2CIACustomerResolution_TestHelper.cls index c344b575..9f47a885 100644 --- a/src/sfdc/base/main/default/classes/B2CIACustomerResolution_TestHelper.cls +++ b/src/sfdc/base/main/default/classes/B2CIACustomerResolution_TestHelper.cls @@ -258,7 +258,7 @@ public with sharing class B2CIACustomerResolution_TestHelper { if (defaultContactModel == 'Person') { // Update the default recordType for the parent Account - accountRecordTypeDeveloperName = 'PersonAccount'; + accountRecordTypeDeveloperName = B2CConfigurationManager.getPersonAccountRecordTypeDeveloperName(); // Retrieve a separate instance of the account (so we can update it) thisAccountToUpdate = [ diff --git a/src/sfdc/base/main/default/classes/B2CIACustomerShopperProfile.cls b/src/sfdc/base/main/default/classes/B2CIACustomerShopperProfile.cls new file mode 100644 index 00000000..85086c84 --- /dev/null +++ b/src/sfdc/base/main/default/classes/B2CIACustomerShopperProfile.cls @@ -0,0 +1,64 @@ +/** + * @author Jordane Bachelet + * @date January 3rd, 2022 + * + * @description This class is used to retrieve a customer profile from the OCAPI Shop API from B2C Commerce. + * The goal of using the Shop API is to retrieve custom data based on customer's context +*/ +public with sharing class B2CIACustomerShopperProfile { + /** + * @description This class is used to process the collection of inputs used to retrieve a + * customer profile from B2C Commerce. When successful, it returns customer profile data. + * + * @param customerShopperProfileInputList {List} Represents the collection of input + * properties used to request an access token + * @return {List} Returns a result representing the access token + * request response (containing a token or the error + */ + @InvocableMethod( + Label='B2C: Get Customer Shopper Profile' + Description='Retrieve the Shopper Customer Profile from B2C Commerce to get data from the current customer\'s context' + ) + public static List getCustomerShopperProfile( + List customerShopperProfileInputList + ) { + List outputObj = new List(); + + for (B2CIACustomerShopperProfileInput b2creq : customerShopperProfileInputList) { + HttpRequest req = B2CHttpRequestHelper.getShopCustomerProfileRequest( + b2creq.domain, b2creq.siteId, b2creq.version, b2creq.customerId, b2creq.clientId, b2creq.token, b2creq.expandParameter + ); + + Http https = new Http(); + HttpResponse res = https.send(req); + B2CIACustomerShopperProfileResult result = new B2CIACustomerShopperProfileResult(); + + result.status = res.getStatus(); + result.statusCode = res.getStatusCode(); + result.responseBody = res.getBody(); + result.isError = false; + + if (result.statusCode == 200) { + JSONParse responseParsedJSON = new JSONParse(res.getBody()); + result.promotionIds = new List(); + try { + List promotionsList = responseParsedJSON.get('c_active_promotions').asList(); + for (JsonParse promotionItem : promotionsList) { + result.promotionIds.add(promotionItem.getStringValue()); + } + } catch (Exception e) { + // No coupons found in the promotion + System.debug('No promotions found for the profile.'); + } + result.totalPromotionsSize = result.promotionIds.size(); + } else { + result.errorMessage = B2CConstant.ERRORS_B2CCOMMERCE_SHOP_CUSTOMER_RETRIEVAL; + result.isError = true; + } + + outputObj.add(result); + } + + return outputObj; + } +} diff --git a/src/sfdc/base/main/default/classes/B2CIACustomerShopperProfile.cls-meta.xml b/src/sfdc/base/main/default/classes/B2CIACustomerShopperProfile.cls-meta.xml new file mode 100644 index 00000000..dd61d1f9 --- /dev/null +++ b/src/sfdc/base/main/default/classes/B2CIACustomerShopperProfile.cls-meta.xml @@ -0,0 +1,5 @@ + + + 52.0 + Active + diff --git a/src/sfdc/base/main/default/classes/B2CIACustomerShopperProfileInput.cls b/src/sfdc/base/main/default/classes/B2CIACustomerShopperProfileInput.cls new file mode 100644 index 00000000..c032fdb9 --- /dev/null +++ b/src/sfdc/base/main/default/classes/B2CIACustomerShopperProfileInput.cls @@ -0,0 +1,27 @@ +/** + * @author Jordane Bachelet + * @date January 3rd, 2022 + * @description This is the input class for customer shopper profile retrieval. + */ +public with sharing class B2CIACustomerShopperProfileInput { + @AuraEnabled @InvocableVariable(Required=true) + public String siteId; + + @AuraEnabled @InvocableVariable(Required=true) + public String customerId; + + @AuraEnabled @InvocableVariable(Required=true) + public String clientId; + + @AuraEnabled @InvocableVariable(Required=true) + public String token; + + @AuraEnabled @InvocableVariable(Required=true) + public String domain; + + @AuraEnabled @InvocableVariable(Required=true) + public String version; + + @AuraEnabled @InvocableVariable(Required=false) + public String expandParameter; +} diff --git a/src/sfdc/base/main/default/classes/B2CIACustomerShopperProfileInput.cls-meta.xml b/src/sfdc/base/main/default/classes/B2CIACustomerShopperProfileInput.cls-meta.xml new file mode 100644 index 00000000..dd61d1f9 --- /dev/null +++ b/src/sfdc/base/main/default/classes/B2CIACustomerShopperProfileInput.cls-meta.xml @@ -0,0 +1,5 @@ + + + 52.0 + Active + diff --git a/src/sfdc/base/main/default/classes/B2CIACustomerShopperProfileResult.cls b/src/sfdc/base/main/default/classes/B2CIACustomerShopperProfileResult.cls new file mode 100644 index 00000000..a24b633d --- /dev/null +++ b/src/sfdc/base/main/default/classes/B2CIACustomerShopperProfileResult.cls @@ -0,0 +1,39 @@ +/** + * @author Jordane Bachelet + * @date January 3rd, 2022 + * + * @description This is the wrapper used by the B2CIACustomerShopperProfile class to capture the B2C Commerce API result +*/ +public class B2CIACustomerShopperProfileResult { + + //////////////////////////////////////////////////////////////// + // Include the REST response properties + //////////////////////////////////////////////////////////////// + @InvocableVariable + public String status; + + @InvocableVariable + public Integer statusCode; + + @InvocableVariable + public String responseBody; + + //////////////////////////////////////////////////////////////// + // Include any error messaging or detail flags + //////////////////////////////////////////////////////////////// + @InvocableVariable + public Boolean isError; + + @InvocableVariable + public String errorMessage; + + //////////////////////////////////////////////////////////////// + // Include the deserialized properties from the response + //////////////////////////////////////////////////////////////// + + @InvocableVariable + public Integer totalPromotionsSize; + + @InvocableVariable + public List promotionIds; +} diff --git a/src/sfdc/base/main/default/classes/B2CIACustomerShopperProfileResult.cls-meta.xml b/src/sfdc/base/main/default/classes/B2CIACustomerShopperProfileResult.cls-meta.xml new file mode 100644 index 00000000..dd61d1f9 --- /dev/null +++ b/src/sfdc/base/main/default/classes/B2CIACustomerShopperProfileResult.cls-meta.xml @@ -0,0 +1,5 @@ + + + 52.0 + Active + diff --git a/src/sfdc/base/main/default/classes/B2CIACustomerShopperProfile_Test.cls b/src/sfdc/base/main/default/classes/B2CIACustomerShopperProfile_Test.cls new file mode 100644 index 00000000..20ee6000 --- /dev/null +++ b/src/sfdc/base/main/default/classes/B2CIACustomerShopperProfile_Test.cls @@ -0,0 +1,69 @@ +/** + * @author Jordane Bachelet + * @date Dec 28, 2021 + * + * @description This class exercises the successful and failed process of customer shopper details retrieval. + */ +@IsTest +private class B2CIACustomerShopperProfile_Test { + @IsTest + static void testIsSuccess() { + Test.startTest(); + Test.setMock(HttpCalloutMock.class, new B2CHttpTestCalloutMockGenerator('CustomerShopDetailsSuccessWithPromotions')); + + // Seed the input arguments + B2CIACustomerShopperProfileInput req = new B2CIACustomerShopperProfileInput(); + req.siteId = 'siteId'; + req.customerId = 'customerId'; + req.clientId = 'clientId'; + req.token = 'token'; + req.domain = 'domain'; + req.version = 'version'; + req.expandParameter = 'parameter'; + + // Request the authToken and validate the results + List resultList = B2CIACustomerShopperProfile.getCustomerShopperProfile( + new List{ + req + } + ); + Test.stopTest(); + + // Validate that the request processed successfully + System.assertEquals(resultList.size() > 0, true, 'Expected a result to be processed and returned in the results'); + System.assertEquals(resultList[0].statusCode, 200, 'Expected a successful http statusCode to be returned as part of this request'); + System.assertEquals(resultList[0].isError, false, 'Expected the isError flag to be false.'); + System.assertEquals(resultList[0].totalPromotionsSize, 2, 'Expected two promotions to be returned from the mock response'); + System.assertEquals(resultList[0].promotionIds.size(), 2, 'Expected two promotions to be returned from the mock response'); + } + + @IsTest + static void testIsFailure() { + Test.startTest(); + Test.setMock(HttpCalloutMock.class, new B2CHttpTestCalloutMockGenerator('CustomerShopDetailsFailure')); + + // Seed the input arguments + B2CIACustomerShopperProfileInput req = new B2CIACustomerShopperProfileInput(); + req.siteId = 'siteId'; + req.customerId = 'customerId'; + req.clientId = 'clientId'; + req.token = 'token'; + req.domain = 'domain'; + req.version = 'version'; + req.expandParameter = 'parameter'; + + // Request the authToken and validate the results + List resultList = B2CIACustomerShopperProfile.getCustomerShopperProfile( + new List{ + req + } + ); + + Test.stopTest(); + + // Validate that the request processed with a failure + System.assertEquals(resultList.size() > 0, true, 'Expected a result to be processed and returned in the results'); + System.assertEquals(resultList[0].statusCode, 400, 'Expected a failed (400) http statusCode to be returned as part of this request'); + System.assertEquals(resultList[0].isError, true, 'Expected the isError flag to be true.'); + } +} diff --git a/src/sfdc/base/main/default/classes/B2CIACustomerShopperProfile_Test.cls-meta.xml b/src/sfdc/base/main/default/classes/B2CIACustomerShopperProfile_Test.cls-meta.xml new file mode 100644 index 00000000..dd61d1f9 --- /dev/null +++ b/src/sfdc/base/main/default/classes/B2CIACustomerShopperProfile_Test.cls-meta.xml @@ -0,0 +1,5 @@ + + + 52.0 + Active + diff --git a/src/sfdc/base/main/default/classes/B2CIAGetAccessTokenResult.cls b/src/sfdc/base/main/default/classes/B2CIAGetAccessTokenResult.cls index 65659ca8..f0491dfa 100644 --- a/src/sfdc/base/main/default/classes/B2CIAGetAccessTokenResult.cls +++ b/src/sfdc/base/main/default/classes/B2CIAGetAccessTokenResult.cls @@ -50,15 +50,4 @@ public class B2CIAGetAccessTokenResult { @InvocableVariable public String b2cInstanceAPIUrl; - - //////////////////////////////////////////////////////////////// - // Include the deserialized properties from the response - //////////////////////////////////////////////////////////////// - - @InvocableVariable - public Integer totalPromotionsSize; - - @InvocableVariable - public List promotionIds; - } diff --git a/src/sfdc/base/main/default/flows/B2CCommerce_B2CPromotion_View_Active_Customer_Promotions_Contacts.flow-meta.xml b/src/sfdc/base/main/default/flows/B2CCommerce_B2CPromotion_View_Active_Customer_Promotions_Contacts.flow-meta.xml index 0847881a..124c981d 100644 --- a/src/sfdc/base/main/default/flows/B2CCommerce_B2CPromotion_View_Active_Customer_Promotions_Contacts.flow-meta.xml +++ b/src/sfdc/base/main/default/flows/B2CCommerce_B2CPromotion_View_Active_Customer_Promotions_Contacts.flow-meta.xml @@ -1,10 +1,59 @@ + + CustomerAuth_Action + + 182 + 1790 + B2CIAAuthCustomerClientCredentialsGrant + apex + + Was_the_Customer_successfully_authenticated + + Automatic + + clientId + + selectedClientId + + + + customerId + + selectedCustomerId + + + + domain + + selectedSiteApi + + + + siteId + + selectedSiteId + + + + token + + ia_getBusinessManagerUserGrant.accessToken + + + + version + + selectedSiteVersion + + + true + Get_Active_Customer_Promotions - 50 - 1910 + 314 + 2702 B2CIAActiveCustomerPromotion apex @@ -58,8 +107,8 @@ Get_the_Customer_Shopper_profile - 182 - 1670 + 446 + 2462 B2CIACustomerShopperProfile apex @@ -75,7 +124,7 @@ customerId - selectedCustomerId + getCustomerProfileCustomerId @@ -99,7 +148,7 @@ token - ia_getBusinessManagerUserGrant.accessToken + getCustomerProfileAccessToken @@ -114,7 +163,7 @@ ... obtain a Business Manager user grant from the B2C Instance. ia_getBusinessManagerUserGrant - 336 + 776 1430 B2CIABusinessManagerGrant apex @@ -141,7 +190,7 @@ ... assign the active B2C Site Count to a local variable. asn_activeB2CSites - 715 + 1287 278 activeB2CSitesCount @@ -165,7 +214,7 @@ ... take the properties from the single B2C Site and copy them to the collection of selected values. asn_selectedB2CSiteValues - 481 + 1009 998 selectedClientId @@ -230,14 +279,64 @@ loop_iterateB2CSites.OOBO_Named_Credential_Developer_Name__c + + selectedOOBOCustomerId + Assign + loop_iterateB2CSites + + Assign_Customer_Access_Token + + 50 + 2030 + + getCustomerProfileAccessToken + Assign + + CustomerAuth_Action.accessToken + + + + getCustomerProfileCustomerId + Assign + + selectedCustomerId + + + + Get_the_Customer_Shopper_profile + + + + Assign_OOBO_Customer_ID_and_BM_Access_Token + + 578 + 1910 + + getCustomerProfileAccessToken + Assign + + ia_getBusinessManagerUserGrant.accessToken + + + + getCustomerProfileCustomerId + Assign + + selectedOOBOCustomerId + + + + Get_the_Customer_Shopper_profile + + Capture_the_selected_customer_Id - 501 + 1029 638 selectedCustomerId @@ -261,8 +360,8 @@ ... evaluate if the customerRetrieval event succeeded with no errors. dec_CustomerRetrieval - 182 - 1790 + 446 + 2582 Screen_Error_Auth @@ -287,7 +386,7 @@ ... evaluate the configuration requirements for Promotion retrieval and determine if the user can proceed. dec_validateConfigRequirements - 501 + 1029 1310 scrn_ConfigurationInvalid @@ -369,7 +468,7 @@ ... evaluate if at least one (1) active B2C Site was retrieved dec_wasActiveB2CSiteFound - 715 + 1287 398 scrn_noActiveB2CSitesFound @@ -395,7 +494,7 @@ ... evaluate if a Business Manager User Grant authToken was returned. dec_wasBMUserGrantAuthTokenReturned - 336 + 776 1550 Screen_Error_Auth @@ -412,7 +511,7 @@ - Get_the_Customer_Shopper_profile + Is_Registered_Customer @@ -421,7 +520,7 @@ ... evaluate if only one site was found among the list of available B2C Sites supporting the active customer promotions retrieval. dec_wasOnlyOneSiteFound - 501 + 1029 758 scrn_b2cSiteSelect @@ -443,6 +542,81 @@ + + Is_Registered_Customer + + 446 + 1670 + + Is_the_OOBO_Customer_ID_available + + Not registered customer + + Registered_Customer + and + + recGet_contactRecord.B2C_Customer_ID__c + IsNull + + false + + + + CustomerAuth_Action + + + + + + Is_the_OOBO_Customer_ID_available + + 710 + 1790 + + Screen_Error_Auth_0 + + OOBO Customer ID not configured + + YES_OOBO_Customer_ID_configured + and + + selectedOOBOCustomerId + IsNull + + false + + + + Assign_OOBO_Customer_ID_and_BM_Access_Token + + + + + + Was_the_Customer_successfully_authenticated + + 182 + 1910 + + Screen_Error_Auth_0_0 + + Error during authentication + + Successfully_authenticated + and + + CustomerAuth_Action.isError + EqualTo + + false + + + + Assign_Customer_Access_Token + + + + ... this flow is used to launch the Order on Behalf Of shopping experience for Service Agents. ... represents the collection of active B2C Sites mapped to the selected / filtered CustomerList. @@ -535,7 +709,7 @@ ... loop over the collection of B2C Sites that are available loop_iterateB2CSites - 393 + 921 878 recGet_activeB2CSites Asc @@ -569,7 +743,7 @@ ... retrieve the collection of active B2C Sites to validate that at least one (1) exists. recGet_activeB2CSites - 715 + 1287 158 false @@ -626,7 +800,7 @@ ... retrieve the contact record used to launch the OOBO flow. recGet_contactRecord - 501 + 1029 518 false @@ -656,8 +830,8 @@ Render_Active_Customer_Promotions - 50 - 2030 + 314 + 2822 false true false @@ -702,8 +876,8 @@ Screen_Error_Auth - 336 - 2402 + 776 + 3194 true true false @@ -847,11 +1021,307 @@ true false + + Screen_Error_Auth_0 + + 842 + 1910 + true + true + false + + lbl_b2cCommerceRESTAPIError_Headline_0 + <p><b style="font-size: 16px;">Unable to retrieve the active customer promotions</b></p> + DisplayText + + + Screen_Error_Auth_0_Section1 + RegionContainer + + Screen_Error_Auth_0_Section1_Column1 + Region + + DisplayText_ErrorWithAuth_0 + <p><b>The customer does not have registration information from B2C Commerce, and no OOBO Customer is configured.</b></p><p>Please ensure to run this flow on a registered customer, or to configure the OOBO Customer.</p> + DisplayText + + + width + + 8 + + + false + + + Screen_Error_Auth_0_Section1_Column2 + Region + + lbl_restAPIError_Image_0 + flowruntime:image + ComponentInstance + + imageName + + astroemergency + + + + horizontalAlignment + + center + + + UseStoredValues + true + true + + + width + + 4 + + + false + + false + + + Screen_Error_Auth_0_Section2 + RegionContainer + + Screen_Error_Auth_0_Section2_Column1 + Region + + lbl_bmUserGrantAuthError_subTitle_0 + <p><b style="font-size: 14px;">Business Manager User Grant</b></p> + DisplayText + + + lbl_BMUserGrantErrorMessage_0 + String + + ia_getBusinessManagerUserGrant.errorMessage + + B2C User Grant Error Message + InputField + false + + + lbl_BMUserGrantResponseBody_0 + + {!ia_getBusinessManagerUserGrant.responseBody} + + B2C User Grant Response Body + LargeTextArea + false + + + width + + 6 + + + false + + + Screen_Error_Auth_0_Section2_Column2 + Region + + lbl_customerAuthError_subTitle_0 + <p><b style="font-size: 14px;">Customer Details</b></p> + DisplayText + + + lbl_customerID + String + + recGet_contactRecord.B2C_Customer_ID__c + + Customer ID + InputField + false + + + lbl_ooboCustomerID + + {!selectedOOBOCustomerId} + + OOBO Customer ID + LargeTextArea + false + + + width + + 6 + + + false + + false + + + lbl_RESTAPIError_0 + <p>Please resolve these error(s) prior to launching another promotions retrieval. Verify that the<a href="https://platform-velocity-6771-dev-ed.lightning.force.com/one/one.app#/settings/personal/ExternalObjectUserSettings/home" rel="noopener noreferrer" target="_blank"><b> Per-User NamedCredential</b></a> for the Service Agent is configured property -- and that the password follows the <a href="https://documentation.b2c.commercecloud.salesforce.com/DOC2/topic/com.demandware.dochelp/OCAPI/current/usage/OAuth.html?cp=0_15_2_23" rel="noopener noreferrer" target="_blank"><b>SFCC "Password:ClientSecret" Based64 encoding structure</b></a>.</p> + DisplayText + + true + false + + + Screen_Error_Auth_0_0 + + 314 + 2030 + true + true + false + + lbl_b2cCommerceRESTAPIError_Headline_0_0 + <p><b style="font-size: 16px;">Unable to retrieve the active customer promotions</b></p> + DisplayText + + + Screen_Error_Auth_0_0_Section1 + RegionContainer + + Screen_Error_Auth_0_0_Section1_Column1 + Region + + DisplayText_ErrorWithAuth_0_0 + <p><b>The B2C Commerce Instance's REST API Responded With an Error</b></p><p>An error occurred when interacting with the B2C Commerce environment and attempting to authenticate the Service Against. Please review the REST API error message(s) below for details regarding this failure.</p><ul><li>The <a href="https://documentation.b2c.commercecloud.salesforce.com/DOC2/topic/com.demandware.dochelp/OCAPI/current/usage/OAuth.html" rel="noopener noreferrer" target="_blank"><b>Business Manager User Grant</b></a> is used to authenticate the Service Agent against the B2C Commerce Instance</li><li>The <a href="https://documentation.b2c.commercecloud.salesforce.com/DOC2/topic/com.demandware.dochelp/OCAPI/current/shop/Resources/Customers.html#id152104953__id-1055795270" rel="noopener noreferrer" target="_blank"><b>OOBO Customer Authentication</b></a> is used to authenticate the B2C Commerce Customer against the selected storefront in order to retrieve its active promotions.</li></ul><p><br></p> + DisplayText + + + width + + 8 + + + false + + + Screen_Error_Auth_0_0_Section1_Column2 + Region + + lbl_restAPIError_Image_0_0 + flowruntime:image + ComponentInstance + + imageName + + astroemergency + + + + horizontalAlignment + + center + + + UseStoredValues + true + true + + + width + + 4 + + + false + + false + + + Screen_Error_Auth_0_0_Section2 + RegionContainer + + Screen_Error_Auth_0_0_Section2_Column1 + Region + + lbl_bmUserGrantAuthError_subTitle_0_0 + <p><b style="font-size: 14px;">Business Manager User Grant</b></p> + DisplayText + + + lbl_BMUserGrantErrorMessage_0_0 + String + + ia_getBusinessManagerUserGrant.errorMessage + + B2C User Grant Error Message + InputField + false + + + lbl_BMUserGrantResponseBody_0_0 + + {!ia_getBusinessManagerUserGrant.responseBody} + + B2C User Grant Response Body + LargeTextArea + false + + + width + + 6 + + + false + + + Screen_Error_Auth_0_0_Section2_Column2 + Region + + lbl_customerAuthError_subTitle_0_0 + <p><b style="font-size: 14px;">Customer Authentication</b></p> + DisplayText + + + lbl_customerAuthErrorMessage_0 + String + + CustomerAuth_Action.errorMessage + + Customer Authentication Error Message + InputField + false + + + lbl_customerAuthResponseBody_0 + + {!CustomerAuth_Action.responseBody} + + Customer Authentication Response Body + LargeTextArea + false + + + width + + 6 + + + false + + false + + + lbl_RESTAPIError_0_0 + <p>Please resolve these error(s) prior to launching another promotions retrieval. Verify that the<a href="https://platform-velocity-6771-dev-ed.lightning.force.com/one/one.app#/settings/personal/ExternalObjectUserSettings/home" rel="noopener noreferrer" target="_blank"><b> Per-User NamedCredential</b></a> for the Service Agent is configured property -- and that the password follows the <a href="https://documentation.b2c.commercecloud.salesforce.com/DOC2/topic/com.demandware.dochelp/OCAPI/current/usage/OAuth.html?cp=0_15_2_23" rel="noopener noreferrer" target="_blank"><b>SFCC "Password:ClientSecret" Based64 encoding structure</b></a>.</p> + DisplayText + + true + false + ... select a B2C Site. scrn_b2cSiteSelect - 609 + 1137 878 false true @@ -936,7 +1406,7 @@ ... explain to the user that the configuration is invalid -- and could not be advanced. scrn_ConfigurationInvalid - 666 + 1282 1430 false true @@ -1071,7 +1541,7 @@ ... no active B2C Sites was configured. OOBO cannot be processed. scrn_noActiveB2CSitesFound - 930 + 1546 518 false true @@ -1143,13 +1613,13 @@ false - 589 + 1161 0 recGet_activeB2CSites - Draft + Active ... records the number of active customerLists present. activeB2CCustomerListCount @@ -1202,6 +1672,20 @@ false false + + getCustomerProfileAccessToken + String + false + false + false + + + getCustomerProfileCustomerId + String + false + false + false + ... describes whether the current shopping session is anonymous or for a specific customer isAnonymousShoppingSession diff --git a/src/sfdc/personaccounts/main/default/classes/B2CIACustomerResolutionPA_Test.cls b/src/sfdc/personaccounts/main/default/classes/B2CIACustomerResolutionPA_Test.cls index 850fa310..aecd4ef4 100644 --- a/src/sfdc/personaccounts/main/default/classes/B2CIACustomerResolutionPA_Test.cls +++ b/src/sfdc/personaccounts/main/default/classes/B2CIACustomerResolutionPA_Test.cls @@ -44,13 +44,14 @@ public class B2CIACustomerResolutionPA_Test { **/ @IsTest static void resolvesCustomerId() { + String accountRecordTypeDeveloperName = B2CConfigurationManager.getPersonAccountRecordTypeDeveloperName(); // Create the test / parent Account Account account = (Account)TestDataFactory.createSObject('Account', new Map{ 'PersonEmail' => 'differntemail@email.com', 'LastName' => 'DifferentLastName', 'B2C_Customer_ID__pc' => 'customerid', - 'RecordTypeId' => [SELECT Id FROM RecordType WHERE DeveloperName = 'PersonAccount' LIMIT 1].Id + 'RecordTypeId' => [SELECT Id FROM RecordType WHERE DeveloperName = :accountRecordTypeDeveloperName LIMIT 1].Id }); // Create the childContact @@ -120,6 +121,7 @@ public class B2CIACustomerResolutionPA_Test { */ @IsTest static void resolvesCustomerNoAndCustomerList() { + String accountRecordTypeDeveloperName = B2CConfigurationManager.getPersonAccountRecordTypeDeveloperName(); // Create the test / parent Account Account account = (Account)TestDataFactory.createSObject('Account', new Map{ @@ -127,7 +129,7 @@ public class B2CIACustomerResolutionPA_Test { 'LastName' => 'DifferentLastName', 'B2C_Customer_No__pc' => 'customerNo', 'B2C_CustomerList_ID__pc' => 'customerList', - 'RecordTypeId' => [SELECT Id FROM RecordType WHERE DeveloperName = 'PersonAccount' LIMIT 1].Id + 'RecordTypeId' => [SELECT Id FROM RecordType WHERE DeveloperName = :accountRecordTypeDeveloperName LIMIT 1].Id }); // Create the childContact @@ -197,13 +199,14 @@ public class B2CIACustomerResolutionPA_Test { */ @IsTest static void resolvesContactWithCustomerListIdLastNameAndEmail() { + String accountRecordTypeDeveloperName = B2CConfigurationManager.getPersonAccountRecordTypeDeveloperName(); // Create the test / parent Account Account account = (Account)TestDataFactory.createSObject('Account', new Map{ 'PersonEmail' => 'email@email.com', 'LastName' => 'LastName', 'B2C_CustomerList_ID__pc' => 'CustomerList', - 'RecordTypeId' => [SELECT Id FROM RecordType WHERE DeveloperName = 'PersonAccount' LIMIT 1].Id + 'RecordTypeId' => [SELECT Id FROM RecordType WHERE DeveloperName = :accountRecordTypeDeveloperName LIMIT 1].Id }); // Create the childContact @@ -272,6 +275,7 @@ public class B2CIACustomerResolutionPA_Test { */ @IsTest static void doesNotResolveDifferentCustomerIds() { + String accountRecordTypeDeveloperName = B2CConfigurationManager.getPersonAccountRecordTypeDeveloperName(); // Create the test / parent Account TestDataFactory.createSObject('Account', new Map{ @@ -279,7 +283,7 @@ public class B2CIACustomerResolutionPA_Test { 'LastName' => 'LastName', 'B2C_Customer_ID__pc' => 'CustomerId', 'B2C_CustomerList_ID__pc' => 'customerList', - 'RecordTypeId' => [SELECT Id FROM RecordType WHERE DeveloperName = 'PersonAccount' LIMIT 1].Id + 'RecordTypeId' => [SELECT Id FROM RecordType WHERE DeveloperName = :accountRecordTypeDeveloperName LIMIT 1].Id }); // Create the childContact @@ -349,13 +353,14 @@ public class B2CIACustomerResolutionPA_Test { */ @IsTest static void createTwoContactsSpanningDifferentCustomerListIds() { + String accountRecordTypeDeveloperName = B2CConfigurationManager.getPersonAccountRecordTypeDeveloperName(); // Create the test / parent Account TestDataFactory.createSObject('Account', new Map{ 'PersonEmail' => 'email@email.com', 'LastName' => 'LastName', 'B2C_CustomerList_ID__pc' => 'customerList', - 'RecordTypeId' => [SELECT Id FROM RecordType WHERE DeveloperName = 'PersonAccount' LIMIT 1].Id + 'RecordTypeId' => [SELECT Id FROM RecordType WHERE DeveloperName = :accountRecordTypeDeveloperName LIMIT 1].Id }); // Create the childContact @@ -424,12 +429,13 @@ public class B2CIACustomerResolutionPA_Test { */ @IsTest static void resolvesContactWithLastNameAndEmail() { + String accountRecordTypeDeveloperName = B2CConfigurationManager.getPersonAccountRecordTypeDeveloperName(); // Create the test / parent Account Account account = (Account)TestDataFactory.createSObject('Account', new Map{ 'PersonEmail' => 'email@email.com', 'LastName' => 'LastName', - 'RecordTypeId' => [SELECT Id FROM RecordType WHERE DeveloperName = 'PersonAccount' LIMIT 1].Id + 'RecordTypeId' => [SELECT Id FROM RecordType WHERE DeveloperName = :accountRecordTypeDeveloperName LIMIT 1].Id }); // Create the childContact diff --git a/test/b2c/int_b2ccrmsync/scripts/hooks/ocapi/shop.customer.test.js b/test/b2c/int_b2ccrmsync/scripts/hooks/ocapi/shop.customer.test.js index 715b673c..4b2f0ed1 100644 --- a/test/b2c/int_b2ccrmsync/scripts/hooks/ocapi/shop.customer.test.js +++ b/test/b2c/int_b2ccrmsync/scripts/hooks/ocapi/shop.customer.test.js @@ -135,12 +135,12 @@ describe('int_b2ccrmsync/cartridge/scripts/b2ccrmsync/hooks/ocapi/shop.customer' }); }); - describe('modifyPOSTResponse', function () { + describe('modifyGETResponse', function () { it('should not do anything in case the B2C CRM Sync site preference is disabled', function () { const site = require('dw-api-mock/dw/system/Site').getCurrent(); site.customPreferences.b2ccrm_syncEnhanceOCAPICustomerResponse = false; requireStub['dw/system/Site'].getCurrent = sandbox.stub().returns(site); - shopCustomerHook.modifyPOSTResponse(customer, customerResponse); + shopCustomerHook.modifyGETResponse(customer, customerResponse); expect(promotionSpy).to.have.not.been.called; }); @@ -150,7 +150,7 @@ describe('int_b2ccrmsync/cartridge/scripts/b2ccrmsync/hooks/ocapi/shop.customer' site.customPreferences.b2ccrm_syncEnhanceOCAPICustomerResponse = true; requireStub['dw/system/Site'].getCurrent = sandbox.stub().returns(site); global.request.getHttpParameters = sandbox.stub().returns({}); - shopCustomerHook.modifyPOSTResponse(customer, customerResponse); + shopCustomerHook.modifyGETResponse(customer, customerResponse); expect(promotionSpy).to.have.not.been.called; }); @@ -166,7 +166,7 @@ describe('int_b2ccrmsync/cartridge/scripts/b2ccrmsync/hooks/ocapi/shop.customer' var promotionPlan = new PromotionPlan([]); requireStub['dw/campaign/PromotionMgr'].getActiveCustomerPromotions = sandbox.stub().returns(promotionPlan); - shopCustomerHook.modifyPOSTResponse(customer, customerResponse); + shopCustomerHook.modifyGETResponse(customer, customerResponse); expect(customerResponse.c_active_promotions).to.exist; expect(customerResponse.c_active_promotions.length).to.be.equal(0); @@ -184,7 +184,7 @@ describe('int_b2ccrmsync/cartridge/scripts/b2ccrmsync/hooks/ocapi/shop.customer' var promotionPlan = new PromotionPlan(promotions); requireStub['dw/campaign/PromotionMgr'].getActiveCustomerPromotions = sandbox.stub().returns(promotionPlan); - shopCustomerHook.modifyPOSTResponse(customer, customerResponse); + shopCustomerHook.modifyGETResponse(customer, customerResponse); expect(customerResponse.c_active_promotions).to.exist; expect(customerResponse.c_active_promotions.length).to.not.be.equal(0);