├── _config.yml ├── .gitattributes ├── supportedimages ├── TurnONOFF.png ├── 1.TriggerSetting.png ├── 2.TriggerSetting.png ├── 3.TriggerSetting.png ├── TriggerPattern.png └── TriggerSetting.png ├── src ├── triggers │ ├── TPM_AccountTrigger.trigger │ ├── AccountTrigger.trigger-meta.xml │ ├── SalesOrderTrigger.trigger-meta.xml │ ├── TPM_AccountTrigger.trigger-meta.xml │ ├── SalesOrderTrigger.trigger │ └── AccountTrigger.trigger ├── classes │ ├── SalesOrderTest.cls-meta.xml │ ├── ApplicationConstant.cls-meta.xml │ ├── IntegrationWrapper.cls-meta.xml │ ├── SalesOrderUtility.cls-meta.xml │ ├── TestDataFactory.cls-meta.xml │ ├── AccountTriggerHandler.cls-meta.xml │ ├── SalesOrderTriggerHandler.cls-meta.xml │ ├── TPM_ApplicationConstant.cls-meta.xml │ ├── TPM_BaseTriggerHandler.cls-meta.xml │ ├── TPM_TriggerDispatcher.cls-meta.xml │ ├── TriggerSettingUtility.cls-meta.xml │ ├── VisualforceController.cls-meta.xml │ ├── LightningComponentController.cls-meta.xml │ ├── LightningComponentWrapper.cls-meta.xml │ ├── TPM_AccountTriggerHandler.cls-meta.xml │ ├── TPM_ApplicationConstant.cls │ ├── ApplicationConstant.cls │ ├── IntegrationWrapper.cls │ ├── LightningComponentWrapper.cls │ ├── VisualforceController.cls │ ├── LightningComponentController.cls │ ├── TPM_TriggerDispatcher.cls │ ├── TPM_BaseTriggerHandler.cls │ ├── SalesOrderUtility.cls │ ├── TPM_AccountTriggerHandler.cls │ ├── AccountTriggerHandler.cls │ ├── SalesOrderTriggerHandler.cls │ ├── TestDataFactory.cls │ ├── SalesOrderTest.cls │ └── TriggerSettingUtility.cls ├── objects │ ├── Account.object │ ├── TriggersSetting__c.object │ └── SalesOrder__c.object ├── package.xml └── customMetadata │ ├── TPM_TriggerSetting.Account.md │ └── TPM_TriggerSetting.Promotion.md └── README.md /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-architect -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto -------------------------------------------------------------------------------- /supportedimages/TurnONOFF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abrarsheikhsony/SFDC-best-practices/HEAD/supportedimages/TurnONOFF.png -------------------------------------------------------------------------------- /supportedimages/1.TriggerSetting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abrarsheikhsony/SFDC-best-practices/HEAD/supportedimages/1.TriggerSetting.png -------------------------------------------------------------------------------- /supportedimages/2.TriggerSetting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abrarsheikhsony/SFDC-best-practices/HEAD/supportedimages/2.TriggerSetting.png -------------------------------------------------------------------------------- /supportedimages/3.TriggerSetting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abrarsheikhsony/SFDC-best-practices/HEAD/supportedimages/3.TriggerSetting.png -------------------------------------------------------------------------------- /supportedimages/TriggerPattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abrarsheikhsony/SFDC-best-practices/HEAD/supportedimages/TriggerPattern.png -------------------------------------------------------------------------------- /supportedimages/TriggerSetting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abrarsheikhsony/SFDC-best-practices/HEAD/supportedimages/TriggerSetting.png -------------------------------------------------------------------------------- /src/triggers/TPM_AccountTrigger.trigger: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // 4 | trigger TPM_AccountTrigger on Account (before insert) { 5 | TPM_TriggerDispatcher.executeTrigger(new TPM_AccountTriggerHandler()); 6 | } -------------------------------------------------------------------------------- /src/classes/SalesOrderTest.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 41.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /src/classes/ApplicationConstant.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 40.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /src/classes/IntegrationWrapper.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 41.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /src/classes/SalesOrderUtility.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 41.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /src/classes/TestDataFactory.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 41.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /src/classes/AccountTriggerHandler.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 40.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /src/classes/SalesOrderTriggerHandler.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 41.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /src/classes/TPM_ApplicationConstant.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 44.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /src/classes/TPM_BaseTriggerHandler.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 44.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /src/classes/TPM_TriggerDispatcher.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 44.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /src/classes/TriggerSettingUtility.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 41.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /src/classes/VisualforceController.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 41.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /src/triggers/AccountTrigger.trigger-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 40.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /src/classes/LightningComponentController.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 41.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /src/classes/LightningComponentWrapper.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 41.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /src/classes/TPM_AccountTriggerHandler.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 44.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /src/triggers/SalesOrderTrigger.trigger-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 41.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /src/triggers/TPM_AccountTrigger.trigger-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 44.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /src/classes/TPM_ApplicationConstant.cls: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // 4 | public with sharing class TPM_ApplicationConstant{ 5 | 6 | public Enum TRIGGER_CONTEXT { 7 | ALL, 8 | BEFORE_INSERT, 9 | BEFORE_UPDATE, 10 | BEFORE_DELETE, 11 | AFTER_INSERT, 12 | AFTER_UPDATE, 13 | AFTER_DELETE, 14 | AFTER_UNDELETE 15 | } 16 | 17 | public static final String SOBJECT_TYPE_ACCOUNT = 'Account'; 18 | 19 | } -------------------------------------------------------------------------------- /src/objects/Account.object: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | BusinessEmail__c 5 | This is the business email address. 6 | false 7 | This is the business email address. 8 | 9 | false 10 | false 11 | Email 12 | false 13 | 14 | -------------------------------------------------------------------------------- /src/classes/ApplicationConstant.cls: -------------------------------------------------------------------------------- 1 | public with sharing class ApplicationConstant{ 2 | 3 | // Types are final by default, use virtual to declare a type that can be extended 4 | public Enum TRIGGER_CONTEXT { 5 | ALL, 6 | BEFORE_INSERT, 7 | BEFORE_UPDATE, 8 | BEFORE_DELETE, 9 | AFTER_INSERT, 10 | AFTER_UPDATE, 11 | AFTER_DELETE, 12 | AFTER_UNDELETE 13 | } 14 | // SObject Types 15 | public static final String SOBJECT_TYPE_APEX_TRIGGER = 'ApexTrigger'; 16 | public static final String SOBJECT_TYPE_APEX_CLASS = 'ApexClass'; 17 | public static final String SOBJECT_TYPE_ACCOUNT = 'Account'; 18 | 19 | public static final String SALES_ORDER_STATUS = 'Approved'; 20 | 21 | } -------------------------------------------------------------------------------- /src/classes/IntegrationWrapper.cls: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------- 2 | Name: IntegrationWrapper.cls 3 | Purpose: A wrapper class of integration 4 | ------------------------------History---------------------------------- 5 | Version Author Date Detail Description 6 | ------- ------- -------------- ------------------ 7 | 1.0 Abrar 25-August-2017 Initial Development 8 | ----------------------------------------------------------------------*/ 9 | public with sharing class IntegrationWrapper{ 10 | 11 | public String firstName; 12 | public String lastName; 13 | public String emailAddress; 14 | public Boolean isActive; 15 | public Boolean isSuccess; 16 | // Other variables here... 17 | 18 | public IntegrationWrapper(){ 19 | firstName = ''; 20 | firstName = ''; 21 | firstName = ''; 22 | isActive = false; 23 | isSuccess = false; 24 | // Other variables here... 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /src/classes/LightningComponentWrapper.cls: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------- 2 | Name: LightningComponentWrapper.cls 3 | Purpose: A wrapper class of Lightning component 4 | ------------------------------History---------------------------------- 5 | Version Author Date Detail Description 6 | ------- ------- -------------- ------------------ 7 | 1.0 Abrar 25-August-2017 Initial Development 8 | ----------------------------------------------------------------------*/ 9 | public with sharing class LightningComponentWrapper{ 10 | 11 | @AuraEnabled public String firstName {get; set;} 12 | @AuraEnabled public String lastName {get; set;} 13 | @AuraEnabled public String emailAddress {get; set;} 14 | @AuraEnabled public Boolean isActive {get; set;} 15 | // Other variables here... 16 | 17 | public LightningComponentWrapper(){ 18 | firstName = ''; 19 | firstName = ''; 20 | firstName = ''; 21 | isActive = false; 22 | // Other variables here... 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /src/classes/VisualforceController.cls: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------- 2 | Name: VisualforceController.cls 3 | Purpose: A controller class of a Visualforce page 4 | ------------------------------History---------------------------------- 5 | Version Author Date Detail Description 6 | ------- ------- -------------- ------------------ 7 | 1.0 Abrar 25-August-2017 Initial Development 8 | ----------------------------------------------------------------------*/ 9 | public with sharing class VisualforceController{ 10 | 11 | public Account accountRecord {get; set;} 12 | 13 | public VisualforceController(){ 14 | accountRecord = new Account(); 15 | 16 | // Code here... 17 | } 18 | 19 | // This is ONLY required if the associated Visualforce page is using a 20 | // StandardController = Account and Extension = VisualforceController 21 | public VisualforceController(ApexPages.StandardController stdController){ 22 | accountRecord = (Account)stdController.getRecord(); 23 | 24 | // Code here... 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /src/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | * 5 | ApexClass 6 | 7 | 8 | * 9 | ApexComponent 10 | 11 | 12 | * 13 | ApexPage 14 | 15 | 16 | * 17 | ApexTestSuite 18 | 19 | 20 | * 21 | ApexTrigger 22 | 23 | 24 | * 25 | AuraDefinitionBundle 26 | 27 | 28 | CustomLabels 29 | CustomLabels 30 | 31 | 32 | * 33 | CustomMetadata 34 | 35 | 36 | Account 37 | SalesOrder__c 38 | CustomObject 39 | 40 | 41 | * 42 | StaticResource 43 | 44 | 41.0 45 | 46 | -------------------------------------------------------------------------------- /src/triggers/SalesOrderTrigger.trigger: -------------------------------------------------------------------------------- 1 | trigger SalesOrderTrigger on SalesOrder__c (before insert, before update, before delete, after insert, after update, after delete, after undelete) { 2 | 3 | SalesOrderTriggerHandler handler = new SalesOrderTriggerHandler(); 4 | 5 | if( Trigger.isBefore ){ 6 | // Execute on Before Insert 7 | if( Trigger.isInsert ){ 8 | handler.OnBeforeInsert(Trigger.new); 9 | } 10 | // Execute on Before Update 11 | if( Trigger.isUpdate ){ 12 | handler.OnBeforeUpdate(Trigger.new, Trigger.old, Trigger.newMap, Trigger.oldMap); 13 | } 14 | // Execute on Before Delete 15 | if( Trigger.isDelete ){ 16 | handler.OnBeforeDelete(Trigger.old, Trigger.oldMap); 17 | } 18 | } 19 | else if( Trigger.isAfter ){ 20 | // Execute on After Insert 21 | if( Trigger.isInsert ){ 22 | handler.OnAfterInsert(Trigger.new, Trigger.newMap); 23 | } 24 | // Execute on After Update 25 | if( Trigger.isUpdate ){ 26 | handler.OnAfterUpdate(Trigger.new, Trigger.old, Trigger.newMap, Trigger.oldMap); 27 | } 28 | // Execute on After Delete 29 | if( Trigger.isDelete ){ 30 | handler.OnAfterDelete(Trigger.old, Trigger.oldMap); 31 | } 32 | // Execute on After Undelete 33 | if( Trigger.isUndelete ){ 34 | handler.OnAfterUndelete(Trigger.new, Trigger.newMap); 35 | } 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /src/classes/LightningComponentController.cls: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------- 2 | Name: LightningComponentController.cls 3 | Purpose: A controller of a Lightning component 4 | ------------------------------History---------------------------------- 5 | Version Author Date Detail Description 6 | ------- ------- -------------- ------------------ 7 | 1.0 Abrar 25-August-2017 Initial Development 8 | ----------------------------------------------------------------------*/ 9 | public with sharing class LightningComponentController{ 10 | 11 | @AuraEnabled public Account accountRecord {get; set;} 12 | 13 | public LightningComponentController(){ 14 | accountRecord = new Account(); 15 | // Code here... 16 | } 17 | 18 | /*---------------------------------------------------------------------- 19 | Purpose: Query and get Account record 20 | Parameters: A valid account record Id 21 | Returns: Account record 22 | ------------------------------History---------------------------------- 23 | Version Author Date Detail Description 24 | ------- ------- -------------- ------------------ 25 | 1.0 Abrar 25-August-2017 Initial Development 26 | ----------------------------------------------------------------------*/ 27 | @AuraEnabled 28 | public static Account getAccount(String pAccountId){ 29 | Account queryAccountRecord = [SELECT Id, Name FROM Account LIMIT 1]; 30 | if( String.isNotBlank(pAccountId) ){ 31 | // Code here... 32 | } 33 | return queryAccountRecord; 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /src/customMetadata/TPM_TriggerSetting.Account.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | false 5 | 6 | TPM_IsDeactivateAfterDelete__c 7 | false 8 | 9 | 10 | TPM_IsDeactivateAfterInsert__c 11 | false 12 | 13 | 14 | TPM_IsDeactivateAfterUnDelete__c 15 | false 16 | 17 | 18 | TPM_IsDeactivateAfterUpdate__c 19 | false 20 | 21 | 22 | TPM_IsDeactivateBeforeDelete__c 23 | false 24 | 25 | 26 | TPM_IsDeactivateBeforeInsert__c 27 | false 28 | 29 | 30 | TPM_IsDeactivateBeforeUpdate__c 31 | false 32 | 33 | 34 | TPM_IsDeactivateTrigger__c 35 | false 36 | 37 | 38 | TPM_ObjectAPIName__c 39 | Account 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/customMetadata/TPM_TriggerSetting.Promotion.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | false 5 | 6 | TPM_IsDeactivateAfterDelete__c 7 | false 8 | 9 | 10 | TPM_IsDeactivateAfterInsert__c 11 | false 12 | 13 | 14 | TPM_IsDeactivateAfterUnDelete__c 15 | false 16 | 17 | 18 | TPM_IsDeactivateAfterUpdate__c 19 | false 20 | 21 | 22 | TPM_IsDeactivateBeforeDelete__c 23 | false 24 | 25 | 26 | TPM_IsDeactivateBeforeInsert__c 27 | false 28 | 29 | 30 | TPM_IsDeactivateBeforeUpdate__c 31 | false 32 | 33 | 34 | TPM_IsDeactivateTrigger__c 35 | false 36 | 37 | 38 | TPM_ObjectAPIName__c 39 | ACCL__Promotion__c 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/classes/TPM_TriggerDispatcher.cls: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // 4 | public with sharing class TPM_TriggerDispatcher{ 5 | 6 | public static void executeTrigger(TPM_BaseTriggerHandler handler){ 7 | if (trigger.isBefore) { 8 | // Execute on Before Insert 9 | if (trigger.isInsert && handler.isTriggerActive(TPM_ApplicationConstant.TRIGGER_CONTEXT.BEFORE_INSERT)) { 10 | handler.beforeInsert (trigger.new); 11 | } 12 | // Execute on Before Update 13 | if (trigger.isUpdate && handler.isTriggerActive(TPM_ApplicationConstant.TRIGGER_CONTEXT.BEFORE_UPDATE)) { 14 | handler.beforeUpdate (trigger.newMap, trigger.oldMap); 15 | } 16 | // Execute on Before Delete 17 | if (trigger.isDelete && handler.isTriggerActive(TPM_ApplicationConstant.TRIGGER_CONTEXT.BEFORE_DELETE)) { 18 | handler.beforeDelete (trigger.oldMap); 19 | } 20 | } 21 | if (trigger.isAfter) { 22 | // Execute on After Insert 23 | if (trigger.isInsert && handler.isTriggerActive(TPM_ApplicationConstant.TRIGGER_CONTEXT.AFTER_INSERT)) { 24 | handler.afterInsert (trigger.newMap); 25 | } 26 | // Execute on After Update 27 | if (trigger.isUpdate && handler.isTriggerActive(TPM_ApplicationConstant.TRIGGER_CONTEXT.AFTER_UPDATE)) { 28 | handler.afterUpdate (trigger.newMap, trigger.oldMap); 29 | } 30 | // Execute on After Delete 31 | if (trigger.isDelete && handler.isTriggerActive(TPM_ApplicationConstant.TRIGGER_CONTEXT.AFTER_DELETE)) { 32 | handler.afterDelete (trigger.oldMap); 33 | } 34 | // Execute on After Undelete 35 | if (trigger.isUndelete && handler.isTriggerActive(TPM_ApplicationConstant.TRIGGER_CONTEXT.AFTER_UNDELETE)) { 36 | handler.afterUndelete(trigger.newMap); 37 | } 38 | } 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /src/classes/TPM_BaseTriggerHandler.cls: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // 4 | public virtual with sharing class TPM_BaseTriggerHandler{ 5 | 6 | public static TPM_TriggerSetting__mdt getTriggerSetting(String objectAPIName){ 7 | TPM_TriggerSetting__mdt triggerSettingRecord = [SELECT Id, TPM_ObjectAPIName__c, TPM_IsDeactivateTrigger__c, 8 | TPM_IsDeactivateBeforeInsert__c, TPM_IsDeactivateBeforeUpdate__c, TPM_IsDeactivateBeforeDelete__c, 9 | TPM_IsDeactivateAfterInsert__c, TPM_IsDeactivateAfterUpdate__c, TPM_IsDeactivateAfterDelete__c, TPM_IsDeactivateAfterUnDelete__c 10 | FROM TPM_TriggerSetting__mdt WHERE TPM_ObjectAPIName__c = :objectAPIName]; 11 | return triggerSettingRecord; 12 | } 13 | 14 | public static Boolean isTriggerActive(String objectAPIName, TPM_ApplicationConstant.TRIGGER_CONTEXT triggerContext){ 15 | TPM_TriggerSetting__mdt triggerSettingRecord = getTriggerSetting(objectAPIName); 16 | 17 | if(triggerSettingRecord.TPM_IsDeactivateTrigger__c){ 18 | return false; 19 | } 20 | 21 | return true; 22 | } 23 | 24 | public virtual Boolean isTriggerActive(TPM_ApplicationConstant.TRIGGER_CONTEXT triggerContext) { 25 | return false; 26 | } 27 | 28 | public virtual void beforeInsert(List lstSobjects) {} 29 | 30 | public virtual void beforeUpdate(Map updatedSobjectsMap, Map oldSobjectsMap) {} 31 | 32 | public virtual void beforeDelete(Map oldSobjectsMap) {} 33 | 34 | public virtual void afterInsert(Map newSobjectsMap) {} 35 | 36 | public virtual void afterUpdate(Map updatedSobjectsMap, Map oldSobjectsMap) {} 37 | 38 | public virtual void afterDelete(Map oldSobjectsMap) {} 39 | 40 | public virtual void afterUndelete(Map newSobjectsMap) {} 41 | 42 | } -------------------------------------------------------------------------------- /src/classes/SalesOrderUtility.cls: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------- 2 | Name: SalesOrderUtility.cls 3 | Purpose: A utility class of SalesOrder__c object 4 | ------------------------------History---------------------------------- 5 | Version Author Date Detail Description 6 | ------- ------- -------------- ------------------ 7 | 1.0 Abrar 25-August-2017 Initial Development 8 | ----------------------------------------------------------------------*/ 9 | public with sharing class SalesOrderUtility{ 10 | 11 | // Must use "@TestVisible" annotation to get access in the test class 12 | @TestVisible private static Boolean hasLineItems = false; 13 | 14 | /*---------------------------------------------------------------------- 15 | Purpose: Calculate the total amount 16 | Parameters: list of SalesOrders 17 | Returns: None 18 | ------------------------------History---------------------------------- 19 | Version Author Date Detail Description 20 | ------- ------- -------------- ------------------ 21 | 1.0 Abrar 25-August-2017 Initial Development 22 | ----------------------------------------------------------------------*/ 23 | public static void calculateTotalAmount(List lstSalesOrders){ 24 | // Code here... 25 | } 26 | 27 | /*---------------------------------------------------------------------- 28 | Purpose: Get Accounts 29 | Parameters: list of SalesOrders 30 | Returns: None 31 | ------------------------------History---------------------------------- 32 | Version Author Date Detail Description 33 | ------- ------- -------------- ------------------ 34 | 1.0 Abrar 25-August-2017 Initial Development 35 | ----------------------------------------------------------------------*/ 36 | // Must use "@TestVisible" annotation to get access in the test class 37 | @TestVisible 38 | private static Set getAccounts(List lstSalesOrders){ 39 | Set setAccountIds = new Set(); 40 | // Code here... 41 | return setAccountIds; 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /src/classes/TPM_AccountTriggerHandler.cls: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------- 2 | Name: TPM_AccountTriggerHandler.cls 3 | Purpose: Trigger Handler of Account object 4 | ------------------------------History---------------------------------- 5 | Version Author Date Detail Description 6 | ------- ------- -------------- ------------------ 7 | 1.0 Abrar 02-November-2018 Initial Development 8 | ----------------------------------------------------------------------*/ 9 | public virtual with sharing class TPM_AccountTriggerHandler extends TPM_BaseTriggerHandler{ 10 | 11 | /*---------------------------------------------------------------------- 12 | Purpose: Check the trigger status 13 | Parameters: 14 | Returns: 15 | ------------------------------History---------------------------------- 16 | Version Author Date Detail Description 17 | ------- ------- -------------- ------------------ 18 | 1.0 Abrar 25-August-2017 Initial Development 19 | ----------------------------------------------------------------------*/ 20 | public override boolean isTriggerActive (TPM_ApplicationConstant.TRIGGER_CONTEXT triggerContext) { 21 | return TPM_BaseTriggerHandler.isTriggerActive(TPM_ApplicationConstant.SOBJECT_TYPE_ACCOUNT, triggerContext); 22 | } 23 | 24 | /*---------------------------------------------------------------------- 25 | Purpose: Execute Before Insert trigger context of Account 26 | Parameters: 27 | Returns: 28 | ------------------------------History---------------------------------- 29 | Version Author Date Detail Description 30 | ------- ------- -------------- ------------------ 31 | 1.0 Abrar 02-November-2018 Initial Development 32 | ----------------------------------------------------------------------*/ 33 | public override void beforeInsert(List lstSObjects){ 34 | for(Account accountRecord : (List)lstSObjects){ 35 | System.Debug('>>TPM_AccountTriggerHandler Before Insert accountRecord<<'+accountRecord); 36 | } 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /src/classes/AccountTriggerHandler.cls: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------- 2 | Name: AccountTriggerHandler.cls 3 | Purpose: Trigger Handler of Account object 4 | ------------------------------History---------------------------------- 5 | Version Author Date Detail Description 6 | ------- ------- -------------- ------------------ 7 | 1.0 Abrar 14-November-2017 Initial Development 8 | ----------------------------------------------------------------------*/ 9 | public with sharing class AccountTriggerHandler{ 10 | 11 | // Execute on Before Insert 12 | public void OnBeforeInsert(List newAccounts){ 13 | // Call a utility class etc. 14 | // Code here... 15 | } 16 | 17 | // Execute on Before Update 18 | public void OnBeforeUpdate(List updatedAccounts, List oldAccounts, Map updatedAccountsMap, Map oldAccountsMap){ 19 | // Call a utility class etc. 20 | // Code here... 21 | } 22 | 23 | // Execute on Before Delete 24 | public void OnBeforeDelete(List oldAccounts, Map oldAccountsMap){ 25 | // Call a utility class etc. 26 | // Code here... 27 | } 28 | 29 | // Execute on After Insert 30 | public void OnAfterInsert(List newAccounts, Map newAccountsMap){ 31 | // Call a utility class etc. 32 | // Code here... 33 | } 34 | 35 | // Execute on After Update 36 | public void OnAfterUpdate(List updatedAccounts, List oldAccounts, Map updatedAccountsMap, Map oldAccountsMap){ 37 | // Call a utility class etc. 38 | // Code here... 39 | } 40 | 41 | // Execute on After Delete 42 | public void OnAfterDelete(List oldAccounts, Map oldAccountsMap){ 43 | // Call a utility class etc. 44 | // Code here... 45 | } 46 | 47 | // Execute on After Undelete 48 | public void OnAfterUndelete(List newAccounts, Map newAccountsMap){ 49 | // Call a utility class etc. 50 | // Code here... 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /src/classes/SalesOrderTriggerHandler.cls: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------- 2 | Name: SalesOrderTriggerHandler.cls 3 | Purpose: Trigger Handler of SalesOrder__c object 4 | ------------------------------History---------------------------------- 5 | Version Author Date Detail Description 6 | ------- ------- -------------- ------------------ 7 | 1.0 Abrar 25-August-2017 Initial Development 8 | ----------------------------------------------------------------------*/ 9 | public with sharing class SalesOrderTriggerHandler{ 10 | 11 | // Execute on Before Insert 12 | public void OnBeforeInsert(List newSalesOrders){ 13 | // Call a utility class etc. 14 | // Code here... 15 | } 16 | 17 | // Execute on Before Update 18 | public void OnBeforeUpdate(List updatedSalesOrders, List oldSalesOrders, Map updatedSalesOrdersMap, Map oldSalesOrdersMap){ 19 | // Call a utility class etc. 20 | // Code here... 21 | } 22 | 23 | // Execute on Before Delete 24 | public void OnBeforeDelete(List oldSalesOrders, Map oldSalesOrdersMap){ 25 | // Call a utility class etc. 26 | // Code here... 27 | } 28 | 29 | // Execute on After Insert 30 | public void OnAfterInsert(List newSalesOrders, Map newSalesOrdersMap){ 31 | // Call a utility class etc. 32 | // Code here... 33 | } 34 | 35 | // Execute on After Update 36 | public void OnAfterUpdate(List updatedSalesOrders, List oldSalesOrders, Map updatedSalesOrdersMap, Map oldSalesOrdersMap){ 37 | // Call a utility class etc. 38 | // Code here... 39 | } 40 | 41 | // Execute on After Delete 42 | public void OnAfterDelete(List oldSalesOrders, Map oldSalesOrdersMap){ 43 | // Call a utility class etc. 44 | // Code here... 45 | } 46 | 47 | // Execute on After Undelete 48 | public void OnAfterUndelete(List newSalesOrders, Map newSalesOrdersMap){ 49 | // Call a utility class etc. 50 | // Code here... 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /src/classes/TestDataFactory.cls: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------- 2 | Name: TestDataFactory.cls 3 | Purpose: A test data factory class of the whole application 4 | (1) You must NOT do any DML operation here. The DML operation 5 | must be done in the test class which would call this data factory class 6 | ------------------------------History---------------------------------- 7 | Version Author Date Detail Description 8 | ------- ------- -------------- ------------------ 9 | 1.0 Abrar 25-August-2017 Initial Development 10 | ----------------------------------------------------------------------*/ 11 | @isTest 12 | public class TestDataFactory{ 13 | 14 | /*---------------------------------------------------------------------- 15 | Purpose: Create records of a custom setting "TriggerSwitch__c" using a 16 | Static Resource "TriggerSwitchResource" 17 | Parameters: None 18 | Returns: None 19 | ------------------------------History---------------------------------- 20 | Version Author Date Detail Description 21 | ------- ------- -------------- ------------------ 22 | 1.0 Abrar 25-August-2017 Initial Development 23 | ----------------------------------------------------------------------*/ 24 | public static List createTriggerSwitchSetting(){ 25 | // Create a sample .csv file "TriggerSwitchResource" and save it in Static Resource 26 | List customSetting = Test.loadData(TriggerSwitch__c.sObjectType, 'TriggerSwitchResource'); 27 | return customSetting; 28 | 29 | // Code here... 30 | } 31 | 32 | /*---------------------------------------------------------------------- 33 | Purpose: Create records of an Account record 34 | Parameters: None 35 | Returns: None 36 | ------------------------------History---------------------------------- 37 | Version Author Date Detail Description 38 | ------- ------- -------------- ------------------ 39 | 1.0 Abrar 25-August-2017 Initial Development 40 | ----------------------------------------------------------------------*/ 41 | public static Account createAccount(String pName, String pRecordTypeId){ 42 | Account accountRecord = new Account(); 43 | accountRecord.Name = pName; 44 | accountRecord.RecordTypeId = pRecordTypeId; 45 | return accountRecord; 46 | } 47 | 48 | // Code here for additional methods... 49 | 50 | } -------------------------------------------------------------------------------- /src/triggers/AccountTrigger.trigger: -------------------------------------------------------------------------------- 1 | trigger AccountTrigger on Account (before insert, before update, before delete, after insert, after update, after delete, after undelete) { 2 | 3 | AccountTriggerHandler handler = new AccountTriggerHandler(); 4 | 5 | if( TriggerSettingUtility.isTriggerActive(ApplicationConstant.SOBJECT_TYPE_ACCOUNT, null) ){ 6 | if( Trigger.isBefore ){ 7 | // Execute on Before Insert 8 | if( Trigger.isInsert && TriggerSettingUtility.isTriggerActive(ApplicationConstant.SOBJECT_TYPE_ACCOUNT, ApplicationConstant.TRIGGER_CONTEXT.BEFORE_INSERT) ){ 9 | handler.OnBeforeInsert(Trigger.new); 10 | } 11 | // Execute on Before Update 12 | if( Trigger.isUpdate && TriggerSettingUtility.isTriggerActive(ApplicationConstant.SOBJECT_TYPE_ACCOUNT, ApplicationConstant.TRIGGER_CONTEXT.BEFORE_UPDATE) ){ 13 | handler.OnBeforeUpdate(Trigger.new, Trigger.old, Trigger.newMap, Trigger.oldMap); 14 | } 15 | // Execute on Before Delete 16 | if( Trigger.isDelete && TriggerSettingUtility.isTriggerActive(ApplicationConstant.SOBJECT_TYPE_ACCOUNT, ApplicationConstant.TRIGGER_CONTEXT.BEFORE_DELETE) ){ 17 | handler.OnBeforeDelete(Trigger.old, Trigger.oldMap); 18 | } 19 | } 20 | else if( Trigger.isAfter ){ 21 | // Execute on After Insert 22 | if( Trigger.isInsert && TriggerSettingUtility.isTriggerActive(ApplicationConstant.SOBJECT_TYPE_ACCOUNT, ApplicationConstant.TRIGGER_CONTEXT.AFTER_INSERT) ){ 23 | handler.OnAfterInsert(Trigger.new, Trigger.newMap); 24 | } 25 | // Execute on After Update 26 | if( Trigger.isUpdate && TriggerSettingUtility.isTriggerActive(ApplicationConstant.SOBJECT_TYPE_ACCOUNT, ApplicationConstant.TRIGGER_CONTEXT.AFTER_UPDATE) ){ 27 | handler.OnAfterUpdate(Trigger.new, Trigger.old, Trigger.newMap, Trigger.oldMap); 28 | } 29 | // Execute on After Delete 30 | if( Trigger.isDelete && TriggerSettingUtility.isTriggerActive(ApplicationConstant.SOBJECT_TYPE_ACCOUNT, ApplicationConstant.TRIGGER_CONTEXT.AFTER_DELETE) ){ 31 | handler.OnAfterDelete(Trigger.old, Trigger.oldMap); 32 | } 33 | // Execute on After Undelete 34 | if( Trigger.isUndelete && TriggerSettingUtility.isTriggerActive(ApplicationConstant.SOBJECT_TYPE_ACCOUNT, ApplicationConstant.TRIGGER_CONTEXT.AFTER_UNDELETE) ){ 35 | handler.OnAfterUndelete(Trigger.new, Trigger.newMap); 36 | } 37 | } 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /src/classes/SalesOrderTest.cls: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------- 2 | Name: SalesOrderTest.cls 3 | Purpose: A test class of SalesOrder__c object 4 | ------------------------------History---------------------------------- 5 | Version Author Date Detail Description 6 | ------- ------- -------------- ------------------ 7 | 1.0 Abrar 25-August-2017 Initial Development 8 | ----------------------------------------------------------------------*/ 9 | /* 10 | Considerations for @isTest(isParallel=true) annotation: 11 | (1) Use the @isTest(isParallel=true) annotation to indicate test classes that can run in parallel and aren’t restricted by the default limits on the number of concurrent tests. This makes the execution of test classes more efficient, because more tests can be run in parallel. 12 | (2) This annotation overrides the default setting (Disable Parallel Apex Testing) that disable parallel testing. 13 | (3) A test class that doesn’t have this annotation is restricted by the default limits on the number of concurrent tests. 14 | */ 15 | @isTest(isParallel=true) 16 | private class SalesOrderTest{ 17 | 18 | /* 19 | Considerations for @testSetup annotation: 20 | (1) Methods with @testSetup annotation are available/supported ONLY with those test classes which are marked as @isTest and NOT with @isTest(SeeAllData=true). 21 | (2) You can have only one test setup method per test class. 22 | (3) Methods defined with the @testSetup annotation are used for creating common test records that are available for all test methods in the class. 23 | (4) If a test class contains a test setup method, the testing framework executes the test setup method first, before any test method in the class. 24 | (5) Records that are created in a test setup method are available to all test methods in the test class and are rolled back at the end of test class execution. 25 | (6) If a test method changes those records, such as record field updates or record deletions, those changes are rolled back after each test method finishes execution. The next executing test method gets access to the original unmodified state of those records. 26 | */ 27 | @testSetup static void setupCommonData(){ 28 | // Create custom setting records 29 | TestDataFactory.createTriggerSwitchSetting(); 30 | 31 | // Code here... 32 | } 33 | 34 | static testMethod void testCaseName1(){ 35 | // Code here... 36 | } 37 | 38 | /* 39 | Recommended Approach: 40 | Using the @isTest annotation instead of the testMethod keyword is more flexible as you can specify parameters in the annotation. 41 | e.g. @isTest(SeeAllData=true) 42 | */ 43 | @isTest static void testCaseName2(){ 44 | // Code here... 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /src/objects/TriggersSetting__c.object: -------------------------------------------------------------------------------- 1 | 2 | 3 | List 4 | A custom setting for all triggers within this application to enable/disable one "or" many trigger contexts (before insert, before update, before delete, after insert, after update, after delete, after undelete). 5 | false 6 | 7 | IsDeactivateAfterDelete__c 8 | false 9 | false 10 | 11 | false 12 | Checkbox 13 | 14 | 15 | IsDeactivateAfterInsert__c 16 | false 17 | false 18 | 19 | false 20 | Checkbox 21 | 22 | 23 | IsDeactivateAfterUnDelete__c 24 | false 25 | false 26 | 27 | false 28 | Checkbox 29 | 30 | 31 | IsDeactivateAfterUpdate__c 32 | false 33 | false 34 | 35 | false 36 | Checkbox 37 | 38 | 39 | IsDeactivateBeforeDelete__c 40 | false 41 | false 42 | 43 | false 44 | Checkbox 45 | 46 | 47 | IsDeactivateBeforeInsert__c 48 | false 49 | false 50 | 51 | false 52 | Checkbox 53 | 54 | 55 | IsDeactivateBeforeUpdate__c 56 | false 57 | false 58 | 59 | false 60 | Checkbox 61 | 62 | 63 | IsDeactivateTrigger__c 64 | false 65 | false 66 | 67 | false 68 | Checkbox 69 | 70 | 71 | Protected 72 | 73 | -------------------------------------------------------------------------------- /src/classes/TriggerSettingUtility.cls: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------- 2 | Name: TriggerSettingUtility.cls 3 | Purpose: A generalised trigger utility for all triggers to enable/disable 4 | one "or" many trigger contexts (before insert, before update, 5 | before delete, after insert, after update, after delete, after undelete) 6 | using a custom setting "Trigger Setting (TriggersSetting__c)". 7 | ------------------------------History---------------------------------- 8 | Version Author Date Detail Description 9 | ------- ------- -------------- ------------------ 10 | 1.0 Abrar 11-November-2017 Initial Development 11 | ----------------------------------------------------------------------*/ 12 | public with sharing class TriggerSettingUtility{ 13 | 14 | /*---------------------------------------------------------------------- 15 | Purpose: Check whether Apex trigger of the specific object should execute or not? 16 | Parameters: SObject API Name 17 | Returns: Flag (True or Active / False or Inactive) 18 | ------------------------------History---------------------------------- 19 | Version Author Date Detail Description 20 | ------- ------- -------------- ------------------ 21 | 1.0 Abrar 11-November-2017 Initial Development 22 | ----------------------------------------------------------------------*/ 23 | public static Boolean isTriggerActive(String objectAPIName, ApplicationConstant.TRIGGER_CONTEXT triggerContext){ 24 | if( String.isNotBlank(objectAPIName) ){ 25 | TriggersSetting__c triggerSetting = TriggersSetting__c.getInstance(objectAPIName); 26 | 27 | if( triggerSetting <> null ){ 28 | if(triggerSetting.IsDeactivateTrigger__c){ 29 | return false; 30 | } 31 | else if(triggerSetting.IsDeactivateBeforeInsert__c && triggerContext == ApplicationConstant.TRIGGER_CONTEXT.BEFORE_INSERT){ 32 | return false; 33 | } 34 | else if(triggerSetting.IsDeactivateBeforeUpdate__c && triggerContext == ApplicationConstant.TRIGGER_CONTEXT.BEFORE_UPDATE){ 35 | return false; 36 | } 37 | else if(triggerSetting.IsDeactivateBeforeDelete__c && triggerContext == ApplicationConstant.TRIGGER_CONTEXT.BEFORE_DELETE){ 38 | return false; 39 | } 40 | else if(triggerSetting.IsDeactivateAfterInsert__c && triggerContext == ApplicationConstant.TRIGGER_CONTEXT.AFTER_INSERT){ 41 | return false; 42 | } 43 | else if(triggerSetting.IsDeactivateAfterUpdate__c && triggerContext == ApplicationConstant.TRIGGER_CONTEXT.AFTER_UPDATE){ 44 | return false; 45 | } 46 | else if(triggerSetting.IsDeactivateAfterDelete__c && triggerContext == ApplicationConstant.TRIGGER_CONTEXT.AFTER_DELETE){ 47 | return false; 48 | } 49 | else if(triggerSetting.IsDeactivateAfterUnDelete__c && triggerContext == ApplicationConstant.TRIGGER_CONTEXT.AFTER_UNDELETE){ 50 | return false; 51 | } 52 | } 53 | } 54 | return true; 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /src/objects/SalesOrder__c.object: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Accept 5 | Default 6 | 7 | 8 | CancelEdit 9 | Default 10 | 11 | 12 | Clone 13 | Default 14 | 15 | 16 | Delete 17 | Default 18 | 19 | 20 | Edit 21 | Default 22 | 23 | 24 | List 25 | Default 26 | 27 | 28 | New 29 | Default 30 | 31 | 32 | SaveEdit 33 | Default 34 | 35 | 36 | Tab 37 | Default 38 | 39 | 40 | View 41 | Default 42 | 43 | false 44 | SYSTEM 45 | Deployed 46 | This object contains orders from SAP. 47 | true 48 | true 49 | false 50 | false 51 | true 52 | true 53 | true 54 | true 55 | 56 | SalesAmount__c 57 | false 58 | 59 | 18 60 | false 61 | 0 62 | false 63 | Currency 64 | 65 | 66 | SalesQuantity__c 67 | false 68 | 69 | 18 70 | false 71 | 0 72 | false 73 | Number 74 | false 75 | 76 | 77 | Status__c 78 | false 79 | 80 | false 81 | false 82 | Picklist 83 | 84 | true 85 | 86 | false 87 | 88 | Approved 89 | false 90 | 91 | 92 | 93 | Not Started 94 | false 95 | 96 | 97 | 98 | Sent 99 | false 100 | 101 | 102 | 103 | Waiting Customer 104 | false 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | All 113 | Everything 114 | 115 | 116 | 117 | SO-{0000} 118 | 119 | AutoNumber 120 | 121 | Sales Orders 122 | 123 | ReadWrite 124 | Public 125 | 126 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Salesforce Best Practices 2 | # With Great Power Comes Great Responsibility! 3 | 4 | 5 | The best applications are coded properly. The "properly" means the code not only does its job well, but is also easy to understand, add to, maintain and debug. 6 | 7 | Coding standards are great! We want to ensure that the Salesforce org is self documented. The consistent and well-written code is critical to ensuring high quality standards across all applications. 8 | 9 | Here you will find the Best Practices (Naming Conventions & Coding Standards) of development components for Salesforce org. 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 31 | 32 | 33 | 34 |
Salesforce Naming Conventions (Point and Click Tools)
ComponentNaming ConventionExample
22 | Custom Object Name
23 | Custom Field Name
24 | Record Types
25 | Validation Rules
26 | Workflow Rules
27 | Approval Processes
28 | Custom Buttons & Links
29 | ......................
30 |
CapitalizedCamelCase without UnderscoresSalesOrder__c
35 | 36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 |
Salesforce Naming Conventions (Apex)
ComponentNaming ConventionExamples with Suffix
Apex TriggerCapitalizedCamelCase without UnderscoresAccountTrigger
Apex Trigger Handler ClassCapitalizedCamelCase without UnderscoresAccountTriggerHandler
Apex Utility ClassCapitalizedCamelCase without UnderscoresAccountUtility
Apex Helper ClassCapitalizedCamelCase without UnderscoresAccountRollupHelper
Apex Wrapper classCapitalizedCamelCase without UnderscoresAccountWrapper
Apex Batch ClassCapitalizedCamelCase without UnderscoresProcessAccountsBatch
Apex Schedule ClassCapitalizedCamelCase without UnderscoresProcessAccountsBatchSchedule
Apex/Visualforce ControllerCapitalizedCamelCase without UnderscoresAccountController
Apex/Visualforce Controller ExtensionCapitalizedCamelCase without UnderscoresAccountControllerExtension
Apex Test Data FactoryCapitalizedCamelCase without UnderscoresAccountTestDataFactory
Apex Test Class NameCapitalizedCamelCase without UnderscoresAccountTest
Apex Class MethodlowerCamelCase without Underscorespublic void calculateSales(){}
Apex Constant Class VariablesCAPITALIZED_WITH_UNDERSCORESpublic static final OBJECT_TYPE_ACCOUNT = ‘Account’;
Boolean VariableslowerCamelCase without UnderscoresisActive, hasErrors, hasLineItems, isSuccess etc.
118 | 119 |
120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 |
Salesforce Naming Conventions (Visualforce / Static Resource / Custom Labels)
ComponentNaming ConventionExamples with Suffix
Visualforce PageCapitalizedCamelCase without UnderscoresViewSales
Static ResourceslowerCamelCase without UnderscorespaginationResource
Custom LabelCapitalizedCamelCase without UnderscoresErrorMessage
146 | 147 |
148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 |
Salesforce Naming Conventions (Lightning)
ComponentNaming ConventionExamples with Suffix
Lightning ApplicationCapitalizedCamelCase without UnderscoresHRMApp
Lightning InterfaceCapitalizedCamelCase without UnderscoresPaginationInterface
Lightning ComponentlowerCamelCase without UnderscoresprocessRecordsComponent
Lightning TokenlowerCamelCase without UnderscoresintegrationCredentialsToken
Lightning Application EventlowerCamelCase with UnderscoresdeleteRecord_AppEvent
Lightning Component EventlowerCamelCase with UnderscoressendAccountToSAP_CompEvent
189 | 190 |
191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 |
Acceptable Keywords & Access Modifiers (Y)
Class Typeglobalpublicprivatewith sharingwithout sharing@isTest annotation@testSetup annotation@TestVisible annotation@AuraEnabled annotation
Apex Constant ClassYY
Apex Trigger HandlerYY
Apex UtilityYYY
Apex HelperYYY
Apex ScheduleYY
Apex BatchYY
Apex WrapperYY
Visualforce ControllerYY
Visualforce Controller ExtensionYY
Lightning ControllerYYY
Apex Test Data FactoryYY
Apex Test ClassYY
Apex Non-Test Class Private VariablesYY
Apex Non-Test Class Private MethodsYY
Apex Setup / Common MethodYY
389 | 390 |
391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 408 | 429 | 430 | 431 | 432 | 440 | 459 | 460 |
Custom Settings
ComponentBest PracticeExamples
List Custom Settings in ApexDon't use SOQL Query to access custom setting. Use following List custom setting methods to access it.
404 | (1) getAll()
405 | (2) getInstance(dataSetName)
406 | (3) getValues(dataSetName)
407 |
(1) Get all records of a custom setting
409 | 410 | Map triggerSetting = TriggerSetting_c.getAll(); 411 | for(String triggerName : triggerSetting.keySet()){ 412 | System.Debug('>>triggerName<<'+triggerName); 413 | System.Debug('>>Trigger flag Activate/Deactivate<<'+triggerSetting.get(triggerName).Deactivate__c); 414 | } 415 | 416 |

(2) Get specific record from the custom setting using literal
417 | 418 | TriggerSetting_c accountTriggerSetting = TriggerSetting_c.getInstance('Account'); 419 | System.Debug('>>accountTriggerSetting<<'+accountTriggerSetting); 420 | System.Debug('>>accountTriggerSetting<<'+accountTriggerSetting.Deactivate__c); 421 | 422 |

(3) Get specific record from the custom setting using literal
423 | 424 | TriggerSetting_c accountTriggerSetting = TriggerSetting_c.getValues('Account'); 425 | System.Debug('>>accountTriggerSetting<<'+accountTriggerSetting); 426 | System.Debug('>>accountTriggerSetting<<'+accountTriggerSetting.Deactivate__c); 427 | 428 |
Hierarchy Custom Setting in ApexDon't use SOQL Query to access custom setting. Use following Hierarchy custom setting methods to access it.
433 | (1) getInstance()
434 | (2) getInstance(userId)
435 | (3) getInstance(profileId)
436 | (4) getOrgDefaults()
437 | (5) getValues(userId)
438 | (6) getValues(profileId)
439 |
(1)
441 | 442 | TPM_ApplicationSetting_c applicationSetting = TPM_ApplicationSetting_c.getOrgDefaults(); 443 | System.Debug('>>applicationSetting<<'+applicationSetting); 444 | System.Debug('>>applicationSetting<<'+applicationSetting.TPM_RecordsPerPage__c); 445 | if( applicationSetting.TPM_RecordsPerPage__c <> null ){ 446 | // Your code here... 447 | } 448 | 449 |
(2)
450 | 451 | TPM_ApplicationSetting_c applicationSetting = TPM_ApplicationSetting_c.getInstance(); 452 | System.Debug('>>applicationSetting<<'+applicationSetting); 453 | System.Debug('>>applicationSetting<<'+applicationSetting.TPM_RecordsPerPage__c); 454 | if( applicationSetting.TPM_RecordsPerPage__c <> null ){ 455 | // Your code here... 456 | } 457 | 458 |
461 | 462 |
463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 483 | 484 |
Custom Metadata Types
Best PracticeExamples
Use SOQL query to access Custom Metadata Type record(1) Access All records
475 | 476 | List lstKPIConfigurations = [SELECT MasterLabel, QualifiedApiName, DeveloperName, TPM_Active__c FROM TPM_KPIConfiguration__mdt]; 477 | 478 |
(2) Access specific record
479 | 480 | TPM_KPIConfiguration__mdt kpiConfiguration = [SELECT MasterLabel, QualifiedApiName, DeveloperName, TPM_Active__c FROM TPM_KPIConfiguration__mdt WHERE QualifiedApiName = 'WaveAnalytics1']; 481 | 482 |
485 | 486 |
487 | 488 | ##### Reference Links for Apex Trigger 489 | (a) Context Variable Considerations
490 | (b) Trigger Context Variables
491 | (c) Triggers and Recovered Records for after undelete trigger
492 | 493 | ##### Reference Links Apex Test Data Factory Class 494 | (a) Get Started with Apex Unit Tests
495 | (b) @isTest(isParallel=true) annotation
496 | (c) Common Test Utility Classes for Test Data Creation
497 | (d) Standard Test Methods
498 | 499 | ##### Reference Links for Apex Test Class 500 | (a) Hello World Trigger Test Class
501 | (b) An Introduction to Apex Code Test Methods
502 | 503 | ## Trigger Setting to enable (Active) or disable (Inactive) trigger on a specific object. 504 | 505 | 506 | 507 | 508 | 509 | 510 | ## Transaction Control in Apex (Savepoint & Rollback) 511 | 512 | ``` 513 | public PageReference saveAccounts(){ 514 | 515 | Savepoint sp = Database.setSavepoint(); 516 | 517 | try{ 518 | // Your code logic here... 519 | } 520 | catch(System.Exception ex){ 521 | 522 | Database.rollback(sp); 523 | 524 | // Show error to user 525 | } 526 | 527 | return null; 528 | 529 | } 530 | ``` 531 | 532 | ## Salesforce Trailmixes 533 | (1) Learn Salesforce with Trailhead
534 | 535 | (2) Salesforce for Starters (useful for Consultants and Functional folks)
536 | 537 | (3) Salesforce for UI/UX Developers (useful for SmartUI and Visualforce developers)
538 | 539 | (4) Apex for Developers
540 | 541 | (5) Integration with Salesforce (useful for Apex developers + Integration folks)
542 | 543 | #### Object Oriented Programming in Apex (useful for Advanced Apex developers) 544 | (6) A Beginner’s Guide to Object-Oriented Programming with Apex
545 | 546 | (7) Apex Enterprise Patterns
547 | 548 | (8) Apex Design Patterns
549 | --------------------------------------------------------------------------------