diff --git a/command/login.go b/command/login.go index 4a96090a..a2b58010 100644 --- a/command/login.go +++ b/command/login.go @@ -17,6 +17,7 @@ type ScratchFeature enumflag.Flag const ( PersonAccounts ScratchFeature = iota + B2BCommerce ContactsToMultipleAccounts FinancialServicesUser StateAndCountryPicklist @@ -35,6 +36,7 @@ const ( var ScratchFeatureIds = map[ScratchFeature][]string{ PersonAccounts: {"PersonAccounts"}, + B2BCommerce: {"B2BCommerce"}, ContactsToMultipleAccounts: {"ContactsToMultipleAccounts"}, FinancialServicesUser: {"FinancialServicesUser"}, StateAndCountryPicklist: {"StateAndCountryPicklist"}, @@ -58,6 +60,7 @@ const ( CommunitiesProduct HealthCloudProduct CRMAnalyticsProduct + B2BCommerceProduct ) var ScratchProductIds = map[ScratchProduct][]string{ @@ -65,6 +68,7 @@ var ScratchProductIds = map[ScratchProduct][]string{ CommunitiesProduct: {"communities"}, HealthCloudProduct: {"healthcloud"}, CRMAnalyticsProduct: {"crmanalytics"}, + B2BCommerceProduct: {"b2bcommerce"}, } type ScratchEdition enumflag.Flag @@ -97,6 +101,7 @@ const ( EnableEnhancedNotes ScratchSetting = iota EnableQuote NetworksEnabled + CommerceEnabled EnableApexApprovalLockUnlock PermsetsInFieldCreation EnableLightningPreviewPref @@ -106,6 +111,7 @@ var ScratchSettingIds = map[ScratchSetting][]string{ EnableEnhancedNotes: {"enableEnhancedNotes"}, EnableQuote: {"enableQuote"}, NetworksEnabled: {"networksEnabled"}, + CommerceEnabled: {"commerceEnabled"}, EnableApexApprovalLockUnlock: {"enableApexApprovalLockUnlock"}, PermsetsInFieldCreation: {"permsetsInFieldCreation"}, EnableLightningPreviewPref: {"enableLightningPreviewPref"}, @@ -190,6 +196,7 @@ var scratchCmd = &cobra.Command{ Available Features: AnalyticsAdminPerms - Enables CRM Analytics admin permissions + B2BCommerce - Enables B2B Commerce Communities - Enables Experience Cloud (Communities) ContactsToMultipleAccounts - Allows a single Contact to be associated with multiple Accounts DevelopmentWave - Enables CRM Analytics development features @@ -206,6 +213,7 @@ Available Features: WavePlatform - Enables Wave Platform (CRM Analytics) Available Products: + b2bcommerce - B2B Commerce (enables B2BCommerce feature and commerceEnabled setting) communities - Experience Cloud (enables Communities feature and networksEnabled setting) crmanalytics - CRM Analytics (enables AnalyticsAdminPerms, WavePlatform, InsightsPlatform, EinsteinAnalyticsPlus, EinsteinBuilderFree, DevelopmentWave) fsc - Financial Services Cloud (enables PersonAccounts, ContactsToMultipleAccounts, FinancialServicesUser) @@ -225,6 +233,7 @@ Available Settings (deployed after org creation): enableEnhancedNotes - Enable Enhanced Notes enableQuote - Enable Quotes networksEnabled - Enable Experience Cloud (Communities) + commerceEnabled - Enable Commerce enableApexApprovalLockUnlock - Allow Apex to lock/unlock approval processes permsetsInFieldCreation - Allow assigning permission sets during field creation enableLightningPreviewPref - Enable Lightning Experience preview pref @@ -241,6 +250,7 @@ Examples: force login scratch --edition Enterprise --product fsc force login scratch --setting enableEnhancedNotes force login scratch --setting enableQuote + force login scratch --product b2bcommerce force login scratch --product communities force login scratch --product crmanalytics force login scratch --product healthcloud @@ -317,6 +327,7 @@ func expandProductsToFeatures(products []ScratchProduct, features []ScratchFeatu CommunitiesProduct: {Communities}, HealthCloudProduct: {HealthCloudAddOn, HealthCloudUser}, CRMAnalyticsProduct: {AnalyticsAdminPerms, WavePlatform, InsightsPlatform, EinsteinAnalyticsPlus, EinsteinBuilderFree, DevelopmentWave}, + B2BCommerceProduct: {B2BCommerce}, } featureSet := make(map[ScratchFeature]bool) @@ -360,6 +371,7 @@ func convertSettingsToStrings(settings []ScratchSetting) []string { func expandProductsToSettings(products []ScratchProduct, settings []ScratchSetting) []string { productSettings := map[ScratchProduct][]ScratchSetting{ CommunitiesProduct: {NetworksEnabled}, + B2BCommerceProduct: {CommerceEnabled}, } settingSet := make(map[ScratchSetting]bool) diff --git a/command/login_test.go b/command/login_test.go index d6d713ec..d68c747e 100644 --- a/command/login_test.go +++ b/command/login_test.go @@ -22,6 +22,16 @@ func TestExpandProductsToFeatures_SingleFeature(t *testing.T) { } } +func TestExpandProductsToFeatures_B2BCommerce(t *testing.T) { + result := expandProductsToFeatures([]ScratchProduct{}, []ScratchFeature{B2BCommerce}, map[string]string{}) + if len(result) != 1 { + t.Fatalf("Expected 1 feature, got %d", len(result)) + } + if result[0] != "B2BCommerce" { + t.Errorf("Expected B2BCommerce, got %s", result[0]) + } +} + func TestExpandProductsToFeatures_MultipleFeatures(t *testing.T) { result := expandProductsToFeatures([]ScratchProduct{}, []ScratchFeature{PersonAccounts, ContactsToMultipleAccounts}, map[string]string{}) if len(result) != 2 { @@ -162,6 +172,16 @@ func TestExpandProductsToFeatures_CommunitiesProduct(t *testing.T) { } } +func TestExpandProductsToFeatures_B2BCommerceProduct(t *testing.T) { + result := expandProductsToFeatures([]ScratchProduct{B2BCommerceProduct}, []ScratchFeature{}, map[string]string{}) + if len(result) != 1 { + t.Errorf("Expected 1 feature from b2bcommerce product, got %d", len(result)) + } + if result[0] != "B2BCommerce" { + t.Errorf("Expected B2BCommerce, got %s", result[0]) + } +} + func TestExpandProductsToFeatures_HealthCloudProduct(t *testing.T) { result := expandProductsToFeatures([]ScratchProduct{HealthCloudProduct}, []ScratchFeature{}, map[string]string{}) if len(result) != 2 { @@ -226,6 +246,16 @@ func TestExpandProductsToSettings_CommunitiesProduct(t *testing.T) { } } +func TestExpandProductsToSettings_B2BCommerceProduct(t *testing.T) { + result := expandProductsToSettings([]ScratchProduct{B2BCommerceProduct}, []ScratchSetting{}) + if len(result) != 1 { + t.Errorf("Expected 1 setting from b2bcommerce product, got %d", len(result)) + } + if result[0] != "commerceEnabled" { + t.Errorf("Expected commerceEnabled, got %s", result[0]) + } +} + func TestExpandProductsToSettings_CommunitiesProductWithAdditionalSetting(t *testing.T) { result := expandProductsToSettings([]ScratchProduct{CommunitiesProduct}, []ScratchSetting{EnableEnhancedNotes}) if len(result) != 2 { @@ -281,6 +311,42 @@ func TestScratchEditionIds_AllEditionsDefined(t *testing.T) { } } +func TestScratchFeatureIds_AllFeaturesDefined(t *testing.T) { + expectedFeatures := map[string]bool{ + "AnalyticsAdminPerms": true, + "B2BCommerce": true, + "Communities": true, + "ContactsToMultipleAccounts": true, + "DevelopmentWave": true, + "EinsteinAnalyticsPlus": true, + "EinsteinBuilderFree": true, + "EventLogFile": true, + "FinancialServicesUser": true, + "HealthCloudAddOn": true, + "HealthCloudUser": true, + "ApexUserModeWithPermset": true, + "InsightsPlatform": true, + "PersonAccounts": true, + "StateAndCountryPicklist": true, + "WavePlatform": true, + } + + if len(ScratchFeatureIds) != len(expectedFeatures) { + t.Errorf("Expected %d features, got %d", len(expectedFeatures), len(ScratchFeatureIds)) + } + + for _, ids := range ScratchFeatureIds { + if len(ids) != 1 { + t.Errorf("Expected 1 ID per feature, got %d", len(ids)) + continue + } + featureName := ids[0] + if !expectedFeatures[featureName] { + t.Errorf("Unexpected feature: %s", featureName) + } + } +} + func TestConvertSettingsToStrings_NoSettings(t *testing.T) { result := convertSettingsToStrings([]ScratchSetting{}) if len(result) != 0 { @@ -318,6 +384,16 @@ func TestConvertSettingsToStrings_NetworksEnabled(t *testing.T) { } } +func TestConvertSettingsToStrings_CommerceEnabled(t *testing.T) { + result := convertSettingsToStrings([]ScratchSetting{CommerceEnabled}) + if len(result) != 1 { + t.Errorf("Expected 1 setting, got %d", len(result)) + } + if result[0] != "commerceEnabled" { + t.Errorf("Expected commerceEnabled, got %s", result[0]) + } +} + func TestConvertSettingsToStrings_EnableApexApprovalLockUnlock(t *testing.T) { result := convertSettingsToStrings([]ScratchSetting{EnableApexApprovalLockUnlock}) if len(result) != 1 { @@ -353,6 +429,7 @@ func TestScratchSettingIds_AllSettingsDefined(t *testing.T) { "enableEnhancedNotes": true, "enableQuote": true, "networksEnabled": true, + "commerceEnabled": true, "enableApexApprovalLockUnlock": true, "permsetsInFieldCreation": true, "enableLightningPreviewPref": true, diff --git a/docs/force_login_scratch.md b/docs/force_login_scratch.md index 3fa08d85..f16d4b5d 100644 --- a/docs/force_login_scratch.md +++ b/docs/force_login_scratch.md @@ -8,6 +8,7 @@ Create scratch org and log in Available Features: AnalyticsAdminPerms - Enables CRM Analytics admin permissions + B2BCommerce - Enables B2B Commerce Communities - Enables Experience Cloud (Communities) ContactsToMultipleAccounts - Allows a single Contact to be associated with multiple Accounts DevelopmentWave - Enables CRM Analytics development features @@ -24,6 +25,7 @@ Available Features: WavePlatform - Enables Wave Platform (CRM Analytics) Available Products: + b2bcommerce - B2B Commerce (enables B2BCommerce feature and commerceEnabled setting) communities - Experience Cloud (enables Communities feature and networksEnabled setting) crmanalytics - CRM Analytics (enables AnalyticsAdminPerms, WavePlatform, InsightsPlatform, EinsteinAnalyticsPlus, EinsteinBuilderFree, DevelopmentWave) fsc - Financial Services Cloud (enables PersonAccounts, ContactsToMultipleAccounts, FinancialServicesUser) @@ -43,6 +45,7 @@ Available Settings (deployed after org creation): enableEnhancedNotes - Enable Enhanced Notes enableQuote - Enable Quotes networksEnabled - Enable Experience Cloud (Communities) + commerceEnabled - Enable Commerce enableApexApprovalLockUnlock - Allow Apex to lock/unlock approval processes permsetsInFieldCreation - Allow assigning permission sets during field creation enableLightningPreviewPref - Enable Lightning Experience preview pref @@ -59,6 +62,7 @@ Examples: force login scratch --edition Enterprise --product fsc force login scratch --setting enableEnhancedNotes force login scratch --setting enableQuote + force login scratch --product b2bcommerce force login scratch --product communities force login scratch --product crmanalytics force login scratch --product healthcloud @@ -96,4 +100,3 @@ force login scratch [flags] ### SEE ALSO * [force login](force_login.md) - Log into Salesforce and store a session token - diff --git a/lib/scratch.go b/lib/scratch.go index 7f1e5783..8b235a5e 100644 --- a/lib/scratch.go +++ b/lib/scratch.go @@ -206,6 +206,7 @@ func buildSettingsMetadata(settings []string) ForceMetadataFiles { apexSettings := false userManagementSettings := false lightningExperienceSettings := false + commerceSettings := false for _, setting := range settings { switch setting { @@ -228,6 +229,8 @@ func buildSettingsMetadata(settings []string) ForceMetadataFiles { true ` files["unpackaged/settings/Communities.settings"] = []byte(communitiesSettings) + case "commerceEnabled": + commerceSettings = true case "enableApexApprovalLockUnlock": apexSettings = true case "permsetsInFieldCreation": @@ -264,6 +267,15 @@ func buildSettingsMetadata(settings []string) ForceMetadataFiles { files["unpackaged/settings/LightningExperience.settings"] = lexBuffer.Bytes() } + if commerceSettings { + var commerceBuffer bytes.Buffer + commerceBuffer.WriteString(` + + true +`) + files["unpackaged/settings/Commerce.settings"] = commerceBuffer.Bytes() + } + return files } diff --git a/lib/scratch_test.go b/lib/scratch_test.go index 9bf65d6a..24281433 100644 --- a/lib/scratch_test.go +++ b/lib/scratch_test.go @@ -69,6 +69,29 @@ func TestBuildSettingsMetadata_ExcludesLightningExperienceSettingsWhenUnused(t * } } +func TestBuildSettingsMetadata_AddsCommerceSettings(t *testing.T) { + files := buildSettingsMetadata([]string{"commerceEnabled"}) + + content, ok := files["unpackaged/settings/Commerce.settings"] + if !ok { + t.Fatalf("Commerce.settings not generated") + } + if !strings.Contains(string(content), "true") { + t.Errorf("Commerce.settings missing commerceEnabled preference:\n%s", content) + } + if !strings.Contains(string(content), "