diff --git a/cumulusci.yml b/cumulusci.yml index aabfb77826..c043ab44ed 100644 --- a/cumulusci.yml +++ b/cumulusci.yml @@ -938,6 +938,40 @@ flows: 2: task: update_admin_profile + enable_gift_entry: + description: Enable the Gift Entry feature. + group: NPSP + steps: + 1: + flow: enable_advanced_mapping + 2: + task: execute_anon + options: + apex: > + String namespace = ('%%%NAMESPACE%%%').replace('__',''); + Type t = Type.forName(namespace, 'Callable_Api'); + Callable apiClass = (Callable)t.newInstance(); + apiClass.call('settings.enablegiftentry', null); + + enable_advanced_mapping: + description: Enable the BDI Advanced Mapping feature. + group: NPSP + steps: + 1: + task: execute_anon + options: + apex: > + String namespace = ('%%%NAMESPACE%%%').replace('__',''); + Type t = Type.forName(namespace, 'Callable_Api'); + Callable apiClass = (Callable)t.newInstance(); + apiClass.call('settings.enableadvancedmapping', null); + 2: + task: custom_settings_value_wait + options: + object: "%%%NAMESPACE%%%Data_Import_Settings__c" + field: "%%%NAMESPACE%%%Field_Mapping_Method__c" + value: "Data Import Field Mapping" + enable_rd2: description: 'Fully configures and enables a Scratch org with Enhanced Recurring Donations (unmanaged code only)' group: NPSP diff --git a/documentation/automation.md b/documentation/automation.md index 29c794fbfb..b842a5e822 100644 --- a/documentation/automation.md +++ b/documentation/automation.md @@ -79,6 +79,20 @@ as well as many other features needed to define the workspace for the org's inte | `enable_crlp` | Task | Enable the NPSP Customizable Rollups feature (works for both Managed and Unmanaged) | | `enable_incremental_rollups` | Task | Configure NPSP Customizable Rollups to activate Incremental Rollups | +### Advanced Mapping + +| Name | Type | Description | +| ----------------------------- | ---- | -------------------------------------------------------------------------------------------- | +| `enable_advanced_mapping` | Flow | Enable the BDI Advanced Mapping feature (unmanaged code only). +| `enable_advanced_mapping_managed` | Flow | Enable the BDI Advanced Mapping feature (managed package only) + +### Gift Entry + +| Name | Type | Description | +| ----------------------------- | ---- | -------------------------------------------------------------------------------------------- | +| `enable_gift_entry` | Flow | Enable the Gift Entry feature (unmanaged code only). +| `enable_gift_entry_managed` | Flow | Enable the Gift Entry feature (managed package only) + ### Enhanced Recurring Donations | Name | Type | Description | diff --git a/force-app/main/default/classes/AdvancedMappingEnablementService.cls b/force-app/main/default/classes/AdvancedMappingEnablementService.cls new file mode 100644 index 0000000000..3d382f992b --- /dev/null +++ b/force-app/main/default/classes/AdvancedMappingEnablementService.cls @@ -0,0 +1,63 @@ +/* + Copyright (c) 2022, Salesforce.org + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Salesforce.org nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ +/** + * @author: Salesforce.org + * @date: 2022 + * @description: Service to enable the advanced mapping feature + */ +public with sharing class AdvancedMappingEnablementService { + + @TestVisible + private BDI_MigrationMappingUtility migrationMappingUtility { + get { + if (migrationMappingUtility == null) { + migrationMappingUtility = new BDI_MigrationMappingUtility(new BDI_MigrationMappingHelper()); + } + return migrationMappingUtility; + } + set; + } + + public Id enable() { + migrationMappingUtility.migrateHelpTextToCustomMetadata(); + + Id deploymentId = CMT_MetadataAPI.deployMetadata( + migrationMappingUtility.queuedMetadataTypesForDeploy, + new BDI_MigrationMappingUtility.DeploymentCallback()); + + return deploymentId; + } + + public Boolean isEnabled() { + Data_Import_Settings__c dataImportSettings = UTIL_CustomSettingsFacade.getDataImportSettings(); + + return dataImportSettings.Field_Mapping_Method__c == BDI_MigrationMappingUtility.DATA_IMPORT_FIELD_MAPPING; + } +} \ No newline at end of file diff --git a/force-app/main/default/classes/AdvancedMappingEnablementService.cls-meta.xml b/force-app/main/default/classes/AdvancedMappingEnablementService.cls-meta.xml new file mode 100644 index 0000000000..f928c8e56b --- /dev/null +++ b/force-app/main/default/classes/AdvancedMappingEnablementService.cls-meta.xml @@ -0,0 +1,5 @@ + + + 53.0 + Active + diff --git a/force-app/main/default/classes/AdvancedMappingEnablementServiceMock.cls b/force-app/main/default/classes/AdvancedMappingEnablementServiceMock.cls new file mode 100644 index 0000000000..87c61911e4 --- /dev/null +++ b/force-app/main/default/classes/AdvancedMappingEnablementServiceMock.cls @@ -0,0 +1,63 @@ +/* + * + * Copyright (c) 2022, Salesforce.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Salesforce.org nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * / + */ +/** +* @author Salesforce.org +* @date 2022 +* @description StubProvider mock for tests +*/ +public with sharing class AdvancedMappingEnablementServiceMock implements StubProvider { + public Boolean enableAdvancedMappingCalled = false; + public Boolean isEnabled = false; + + public void setEnabled() { + isEnabled = true; + } + + public Object handleMethodCall( + Object stubbedObject, + String stubbedMethodName, + Type returnType, + List listOfParamTypes, + List listOfParamNames, + List listOfArgs) { + + switch on (stubbedMethodName) { + when 'enable' { + enableAdvancedMappingCalled = true; + } + when 'isEnabled' { + return isEnabled; + } + } + return null; + } +} \ No newline at end of file diff --git a/force-app/main/default/classes/AdvancedMappingEnablementServiceMock.cls-meta.xml b/force-app/main/default/classes/AdvancedMappingEnablementServiceMock.cls-meta.xml new file mode 100644 index 0000000000..f928c8e56b --- /dev/null +++ b/force-app/main/default/classes/AdvancedMappingEnablementServiceMock.cls-meta.xml @@ -0,0 +1,5 @@ + + + 53.0 + Active + diff --git a/force-app/main/default/classes/AdvancedMappingEnablementService_TEST.cls b/force-app/main/default/classes/AdvancedMappingEnablementService_TEST.cls new file mode 100644 index 0000000000..ab316753a3 --- /dev/null +++ b/force-app/main/default/classes/AdvancedMappingEnablementService_TEST.cls @@ -0,0 +1,107 @@ +/* + Copyright (c) 2022, Salesforce.org + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Salesforce.org nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ +@IsTest +private class AdvancedMappingEnablementService_TEST { + + @IsTest + private static void shouldExecuteHelpTextMigrationOnEnable() { + AdvancedMappingEnablementService mappingService = new AdvancedMappingEnablementService(); + BDI_MigrationMappingUtilityMock migrationMappingUtilityMock = new BDI_MigrationMappingUtilityMock(); + mappingService.migrationMappingUtility = stubFor(migrationMappingUtilityMock); + mappingService.migrationMappingUtility.queuedMetadataTypesForDeploy = getMockMetadata(); + + Test.startTest(); + mappingService.enable(); + Test.stopTest(); + + System.assert(migrationMappingUtilityMock.migrateHelpTextCalled, 'The migration of help text to custom ' + + 'metadata should execute.'); + } + + @IsTest + private static void shouldUpdateCustomSettingsForDataImportFieldMapping() { + BDI_MigrationMappingUtility.DeploymentCallback callback = new BDI_MigrationMappingUtility.DeploymentCallback(); + TestingDeployCallbackContext context = new TestingDeployCallbackContext(); + + Metadata.DeployResult deployResult = new Metadata.DeployResult(); + deployResult.status = Metadata.DeployStatus.Succeeded; + + Test.startTest(); + callback.handleResult(deployResult, context); + Test.stopTest(); + + Data_Import_Settings__c dataImportSettings = UTIL_CustomSettingsFacade.getDataImportSettings(); + + System.assertNotEquals(Metadata.DeployStatus.Succeeded.name(), dataImportSettings.CMT_API_Status__c); + + + System.assert(new AdvancedMappingEnablementService().isEnabled(), 'Advanced mapping should be enabled.'); + } + + private static List getMockMetadata() { + List mockCustomMetadataRecords = new List(); + Metadata.CustomMetadata mockCustomMetadata1 = new Metadata.CustomMetadata(); + + mockCustomMetadata1.description = 'test'; + mockCustomMetadata1.fullName = 'test_metadata'; + mockCustomMetadata1.label = 'test'; + mockCustomMetadataRecords.add(mockCustomMetadata1); + + return mockCustomMetadataRecords; + } + + private static BDI_MigrationMappingUtility stubFor(BDI_MigrationMappingUtilityMock migrationMappingUtilityMock) { + + return (BDI_MigrationMappingUtility) Test.createStub( + BDI_MigrationMappingUtility.class, migrationMappingUtilityMock); + } + + private class BDI_MigrationMappingUtilityMock implements StubProvider { + private Boolean migrateHelpTextCalled = false; + + public Object handleMethodCall(Object stubbedObject, String stubbedMethodName, Type returnType, + List listOfParamTypes, List listOfParamNames, List listOfArgs) { + + switch on (stubbedMethodName) { + when 'migrateHelpTextToCustomMetadata' { + migrateHelpTextCalled = true; + } + } + + return null; + } + } + + private class TestingDeployCallbackContext extends Metadata.DeployCallbackContext { + public override Id getCallbackJobId() { + return '000000000122345'; + } + } +} \ No newline at end of file diff --git a/force-app/main/default/classes/AdvancedMappingEnablementService_TEST.cls-meta.xml b/force-app/main/default/classes/AdvancedMappingEnablementService_TEST.cls-meta.xml new file mode 100644 index 0000000000..f928c8e56b --- /dev/null +++ b/force-app/main/default/classes/AdvancedMappingEnablementService_TEST.cls-meta.xml @@ -0,0 +1,5 @@ + + + 53.0 + Active + diff --git a/force-app/main/default/classes/Callable_API.cls b/force-app/main/default/classes/Callable_API.cls index 591b59b0c5..50e754ba7a 100644 --- a/force-app/main/default/classes/Callable_API.cls +++ b/force-app/main/default/classes/Callable_API.cls @@ -42,6 +42,29 @@ global with sharing class Callable_API implements System.Callable { ********************************************************************************************************/ public class MalformedMethodInvocationException extends Exception {} + + @TestVisible + private AdvancedMappingEnablementService advancedMappingEnablementService { + get { + if (advancedMappingEnablementService == null) { + advancedMappingEnablementService = new AdvancedMappingEnablementService(); + } + return advancedMappingEnablementService; + } + set; + } + + @TestVisible + private GiftEntryEnablementService giftEntryEnablementService { + get { + if (giftEntryEnablementService == null) { + giftEntryEnablementService = new GiftEntryEnablementService(); + } + return giftEntryEnablementService; + } + set; + } + /******************************************************************************************************* * @description call function implementation of the callable Interface will dispatch to the appropriate * action handler based on the action text @@ -159,7 +182,25 @@ global with sharing class Callable_API implements System.Callable { // It returns the Job ID of the Scheduled Job. return CallableApiApexDelegationService.handleApexScheduleJob(params); - } when else { + } when 'settings.enableadvancedmapping' { + if (advancedMappingEnablementService.isEnabled()) { + return null; + } + + advancedMappingEnablementService.enable(); + + return null; + + } when 'settings.enablegiftentry' { + if (giftEntryEnablementService.isEnabled()) { + return null; + } + + giftEntryEnablementService.enable(); + + return null; + } + when else { throw new MalformedMethodInvocationException( String.format(System.Label.CallableApiMethodNotImplemented, new List { action }) ); @@ -169,5 +210,4 @@ global with sharing class Callable_API implements System.Callable { // if the action does not return a value then return success return true; } - } diff --git a/force-app/main/default/classes/Callable_API_TEST.cls b/force-app/main/default/classes/Callable_API_TEST.cls index 8f8aceb8fe..113fec396e 100644 --- a/force-app/main/default/classes/Callable_API_TEST.cls +++ b/force-app/main/default/classes/Callable_API_TEST.cls @@ -43,6 +43,8 @@ private with sharing class Callable_API_TEST { private static final String RD2_ENABLE_ACTION = 'Settings.EnableEnhancedRecurringDonations'; private static final String JOB_SCHEDULE_ACTION = 'Apex.ScheduleJob'; private static final String RD2_PAUSE_ACTION = 'rd2.pause'; + private static final String ADVANCED_MAPPING_ACTION = 'settings.enableadvancedmapping'; + private static final String GIFT_ENTRY_ACTION = 'settings.enablegiftentry'; /** * @description verify the TDTM Callable action returns an Object @@ -117,6 +119,68 @@ private with sharing class Callable_API_TEST { Test.stopTest(); } + @IsTest + private static void shouldCallEnableAdvancedMappingOnAction() { + Callable_API callableApi = new Callable_API(); + AdvancedMappingEnablementServiceMock mappingServiceMock = new AdvancedMappingEnablementServiceMock(); + callableApi.advancedMappingEnablementService = stubFor(mappingServiceMock); + + Test.startTest(); + callableApi.call(ADVANCED_MAPPING_ACTION, null); + Test.stopTest(); + + System.assert(mappingServiceMock.enableAdvancedMappingCalled, 'The enable advanced mapping service method ' + + 'should be called.'); + } + + @IsTest + private static void shouldNotCallEnableAdvancedMappingIfMappingIsEnabled() { + Callable_API callableApi = new Callable_API(); + AdvancedMappingEnablementServiceMock mappingServiceMock = new + AdvancedMappingEnablementServiceMock(); + mappingServiceMock.setEnabled(); + + callableApi.advancedMappingEnablementService = stubFor(mappingServiceMock); + + Test.startTest(); + callableApi.call(ADVANCED_MAPPING_ACTION, null); + Test.stopTest(); + + System.assert(!mappingServiceMock.enableAdvancedMappingCalled, 'The enable advanced mapping service method ' + + 'should not be called.'); + } + + @IsTest + private static void shouldCallEnableGiftEntryOnAction() { + Callable_API callableApi = new Callable_API(); + GiftEntryEnablementServiceMock giftEntryEnablementServiceMock = new GiftEntryEnablementServiceMock(); + + callableApi.giftEntryEnablementService = stubFor(giftEntryEnablementServiceMock); + + Test.startTest(); + callableApi.call(GIFT_ENTRY_ACTION, null); + Test.stopTest(); + + System.assert(giftEntryEnablementServiceMock.enableGiftEntryCalled, 'The enable gift entry service method ' + + 'should be called.'); + } + + @IsTest + private static void shouldNotCallEnableGiftEntryIfAlreadyEnabled() { + GiftEntryEnablementServiceMock giftEntryEnablementServiceMock = new GiftEntryEnablementServiceMock(); + giftEntryEnablementServiceMock.setEnabled(); + + Callable_API callableApi = new Callable_API(); + callableApi.giftEntryEnablementService = stubFor(giftEntryEnablementServiceMock); + + Test.startTest(); + callableApi.call(ADVANCED_MAPPING_ACTION, null); + Test.stopTest(); + + System.assert(!giftEntryEnablementServiceMock.enableGiftEntryCalled, 'The enable gift entry service ' + + 'method should not be called.'); + } + /** * @description Verifies if Enhanced Recurring Donations are enabled */ @@ -189,4 +253,43 @@ private with sharing class Callable_API_TEST { new List { UTIL_UnitTestData_TEST.MOCK_ACCOUNT_ID }); System.assertEquals(expectedErrorMessage, returnPause.error, 'An error with unexpected Id should be return'); } + + private static GiftEntryEnablementService stubFor(GiftEntryEnablementServiceMock giftEntryEnablementServiceMock) { + return (GiftEntryEnablementService) Test.createStub( + GiftEntryEnablementService.class, giftEntryEnablementServiceMock); + } + + private static AdvancedMappingEnablementService stubFor(AdvancedMappingEnablementServiceMock + advancedMappingControllerMock) { + return (AdvancedMappingEnablementService) Test.createStub( + AdvancedMappingEnablementService.class, advancedMappingControllerMock); + } + + private class GiftEntryEnablementServiceMock implements StubProvider { + Boolean enableGiftEntryCalled = false; + Boolean isEnabled = false; + + public void setEnabled() { + isEnabled = true; + } + + public Object handleMethodCall( + Object stubbedObject, + String stubbedMethodName, + Type returnType, + List listOfParamTypes, + List listOfParamNames, + List listOfArgs) { + + switch on (stubbedMethodName) { + when 'enable' { + enableGiftEntryCalled = true; + } + when 'isEnabled' { + return isEnabled; + } + } + return null; + } + } } diff --git a/force-app/main/default/classes/GiftEntryEnablementService.cls b/force-app/main/default/classes/GiftEntryEnablementService.cls new file mode 100644 index 0000000000..93e3f051ee --- /dev/null +++ b/force-app/main/default/classes/GiftEntryEnablementService.cls @@ -0,0 +1,63 @@ +/** + Copyright (c) 2022, Salesforce.org + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Salesforce.org nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ +/** +* @author Salesforce.org +* @date 2022 +* @description Enablement Service for the Gift Entry feature +*/ +public with sharing class GiftEntryEnablementService { + @TestVisible + private AdvancedMappingEnablementService advancedMappingEnablementService { + get { + if (advancedMappingEnablementService == null) { + advancedMappingEnablementService = new AdvancedMappingEnablementService(); + } + return advancedMappingEnablementService; + } + set; + } + + public Boolean isEnabled() { + return UTIL_CustomSettingsFacade.getGiftEntrySettings().Enable_Gift_Entry__c; + } + + public void enable() { + if (!advancedMappingEnablementService.isEnabled()) { + throw new GiftEntryEnablementException(System.Label.geServiceLevelErrorAdvancedMapping); + } + + Gift_Entry_Settings__c giftEntrySettings = UTIL_CustomSettingsFacade.getGiftEntrySettings(); + giftEntrySettings.Enable_Gift_Entry__c = true; + + upsert giftEntrySettings; + } + + public class GiftEntryEnablementException extends Exception {} +} \ No newline at end of file diff --git a/force-app/main/default/classes/GiftEntryEnablementService.cls-meta.xml b/force-app/main/default/classes/GiftEntryEnablementService.cls-meta.xml new file mode 100644 index 0000000000..f928c8e56b --- /dev/null +++ b/force-app/main/default/classes/GiftEntryEnablementService.cls-meta.xml @@ -0,0 +1,5 @@ + + + 53.0 + Active + diff --git a/force-app/main/default/classes/GiftEntryEnablement_TEST.cls b/force-app/main/default/classes/GiftEntryEnablement_TEST.cls new file mode 100644 index 0000000000..74f035a9d9 --- /dev/null +++ b/force-app/main/default/classes/GiftEntryEnablement_TEST.cls @@ -0,0 +1,72 @@ +/* + Copyright (c) 2022, Salesforce.org + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Salesforce.org nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ +@IsTest +private class GiftEntryEnablement_TEST { + + @IsTest + private static void enableShouldUpdateCustomSetting() { + GiftEntryEnablementService giftEntryEnablementService = new GiftEntryEnablementService(); + AdvancedMappingEnablementServiceMock advancedMappingEnablementServiceMock = new + AdvancedMappingEnablementServiceMock(); + advancedMappingEnablementServiceMock.setEnabled(); + + giftEntryEnablementService.advancedMappingEnablementService = (AdvancedMappingEnablementService)Test.createStub( + AdvancedMappingEnablementService.class, advancedMappingEnablementServiceMock); + + Test.startTest(); + giftEntryEnablementService.enable(); + Test.stopTest(); + + System.assert(giftEntryEnablementService.isEnabled(), 'Gift entry should be enabled'); + } + + @IsTest + private static void enableThrowsExceptionWhenMappingIsNotEnabled() { + GiftEntryEnablementService giftEntryEnablementService = new GiftEntryEnablementService(); + AdvancedMappingEnablementServiceMock advancedMappingEnablementServiceMock = new + AdvancedMappingEnablementServiceMock(); + + giftEntryEnablementService.advancedMappingEnablementService = (AdvancedMappingEnablementService)Test.createStub( + AdvancedMappingEnablementService.class, advancedMappingEnablementServiceMock); + + GiftEntryEnablementService.GiftEntryEnablementException enablementException; + + Test.startTest(); + try { + giftEntryEnablementService.enable(); + } catch(GiftEntryEnablementService.GiftEntryEnablementException ex) { + enablementException = ex; + } + Test.stopTest(); + + System.assert(enablementException != null, 'An exception should be thrown when advanced mapping is not ' + + 'enabled.'); + } +} \ No newline at end of file diff --git a/force-app/main/default/classes/GiftEntryEnablement_TEST.cls-meta.xml b/force-app/main/default/classes/GiftEntryEnablement_TEST.cls-meta.xml new file mode 100644 index 0000000000..f928c8e56b --- /dev/null +++ b/force-app/main/default/classes/GiftEntryEnablement_TEST.cls-meta.xml @@ -0,0 +1,5 @@ + + + 53.0 + Active + diff --git a/force-app/main/default/classes/STG_PanelDataImportAdvancedMapping_CTRL.cls b/force-app/main/default/classes/STG_PanelDataImportAdvancedMapping_CTRL.cls index d8d5b31a2f..80106f24d3 100644 --- a/force-app/main/default/classes/STG_PanelDataImportAdvancedMapping_CTRL.cls +++ b/force-app/main/default/classes/STG_PanelDataImportAdvancedMapping_CTRL.cls @@ -137,6 +137,17 @@ public with sharing class STG_PanelDataImportAdvancedMapping_CTRL extends STG_Pa set; } + @TestVisible + private AdvancedMappingEnablementService advancedMappingEnablementService { + get { + if (advancedMappingEnablementService == null) { + advancedMappingEnablementService = new AdvancedMappingEnablementService(); + } + return advancedMappingEnablementService; + } + set; + } + /******************************************************************************************************* * @description Instance of BDI_MigrationMappingUtility */ @@ -195,13 +206,9 @@ public with sharing class STG_PanelDataImportAdvancedMapping_CTRL extends STG_Pa isPolling = true; // Start the migration, collect help text mappings, and compare against existing cmt mappings - migrationMappingUtility.migrateHelpTextToCustomMetadata(); + Id metadataDeploymentId = advancedMappingEnablementService.enable(); - Id deploymentId = CMT_MetadataAPI.deployMetadata( - migrationMappingUtility.queuedMetadataTypesForDeploy, - new BDI_MigrationMappingUtility.DeploymentCallback()); - - saveDeploymentId(deploymentId); + saveDeploymentId(metadataDeploymentId); } catch (Exception e) { Database.rollback(sp); @@ -363,16 +370,14 @@ public with sharing class STG_PanelDataImportAdvancedMapping_CTRL extends STG_Pa * @return null */ public PageReference enableGiftEntry() { - Gift_Entry_Settings__c giftEntrySettings = - GE_GiftEntryController.getGiftEntrySettings(); - if (!giftEntrySettings.Enable_Gift_Entry__c) { - giftEntrySettings.Enable_Gift_Entry__c = true; + GiftEntryEnablementService giftEntryEnablementService = new GiftEntryEnablementService(); + if (!giftEntryEnablementService.isEnabled()) { try { - upsert giftEntrySettings; + giftEntryEnablementService.enable(); addPageMessage(ApexPages.Severity.CONFIRM, System.Label.geEnableGiftEntrySuccess); - } catch(DmlException e) { + } catch(Exception e) { addPageMessage(ApexPages.Severity.ERROR, - e.getDmlMessage(0)); + e.getMessage()); } } return null; diff --git a/force-app/main/default/labels/CustomLabels.labels-meta.xml b/force-app/main/default/labels/CustomLabels.labels-meta.xml index cd5558859c..cfa90af94d 100644 --- a/force-app/main/default/labels/CustomLabels.labels-meta.xml +++ b/force-app/main/default/labels/CustomLabels.labels-meta.xml @@ -8802,6 +8802,14 @@ If preferred, you can disable Gift Entry and instead use older Batch Gift Entry Page-level error message body when Advanced Mapping and Gift Entry are off This feature requires both Advanced Mapping and Gift Entry. Please enable them in NPSP Settings. + + geServiceLevelErrorAdvancedMapping + Gift Entry + en_US + true + Service-level error message when advanced mapping is not enabled. + You must enable Advanced Mapping before you can enable Gift Entry. + geErrorPageLevelAdvancedMappingHeader Gift Entry