├── .sfdx └── tools │ └── apex.db ├── .vim-force.com └── session.properties ├── .vscode └── settings.json ├── AccountAddressTrigger.tgr ├── AccountDeletion.tgr ├── AccountHandler.cls ├── AddRelatedRecordTrigger.tgr ├── Aura Components ├── ExpenseController.cls ├── ExpensesController.cls ├── README.md ├── expenses.cmp.xml ├── messages.cmp.xml └── packItemController.js ├── AutomaticProperty.cls ├── BasicProperty.cls ├── Coinbase ├── Components │ └── onb_SelfRegistrationEntityDetails │ │ └── onb_SelfRegistrationEntityDetails.cmp.xml ├── Picklist.md ├── SelfRegistrationEntityDetails │ ├── onb_LightningSelfRegisterController │ │ ├── LIghtningSelfRegisterControllerTest.cls │ │ ├── TestData.cls │ │ └── onb_LightningSelfRegisterControllerTest.cls │ ├── onb_SelfRegistrationEntityDetails.cmp.xml │ └── onb_SelfRegistrationEntityDetailsHelper.js ├── onb_ApplicationFormComponent │ └── onb_ApplicationForm.cmp.xml └── onb_RegisterEntityDetailsController │ ├── onb_RegisterEntityDetailsController.cls │ └── onb_RegisterEntityDetailsControllerTest.cls ├── ContactAndLeadSearch.cls ├── ContactSearch.cls ├── ContactSearchV2.cls ├── EmailManager.cls ├── ExampleClass.cls ├── ExampleTrigger.tgr ├── ExtendedClassExample.cls ├── Notes.md ├── PassNonPrimitiveTypeExample.cls ├── PassPrimitiveTypeExample.cls ├── README.md ├── SOQL.cls ├── SOSLApexExampls.cls ├── SiteRegisterController └── SiteRegisterController.cls ├── Testing Apex ├── CentralizeObjectInitialization.cls ├── CommunityHomeControllerTest.cls ├── DiagnosticsMain.cls ├── DiagnosticsMainTest.cls ├── SampleTest.cls ├── VisibleSampleClass.cls └── onb_RegisterEntityDetailsControllerTest.cls └── VisibleSampleClass ├── Opportunity Contact Role ├── Opportunity1.tgr └── OpportunityContactRole.cls └── VisibleSampleClass.cls /.sfdx/tools/apex.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalesforceSFDC/Apex-Patterns/eb974966326a0888687d2df2e1994647b0235035/.sfdx/tools/apex.db -------------------------------------------------------------------------------- /.vim-force.com/session.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SalesforceSFDC/Apex-Patterns/eb974966326a0888687d2df2e1994647b0235035/.vim-force.com/session.properties -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "git.ignoreLimitWarning": true, 3 | "terminal.integrated.env.osx": { 4 | "SFDX_SET_CLIENT_IDS": "sfdx-vscode" 5 | }, 6 | "terminal.integrated.env.linux": { 7 | "SFDX_SET_CLIENT_IDS": "sfdx-vscode" 8 | }, 9 | "terminal.integrated.env.windows": { 10 | "SFDX_SET_CLIENT_IDS": "sfdx-vscode" 11 | } 12 | } -------------------------------------------------------------------------------- /AccountAddressTrigger.tgr: -------------------------------------------------------------------------------- 1 | trigger AccountAddressTrigger on Account (before insert,before update) { 2 | 3 | //Iterate all accounts that is updated or inserted. 4 | for(Account acc :Trigger.New){ 5 | //if match is true set values. 6 | if(acc.Match_Billing_Address__c){ 7 | acc.ShippingPostalCode = acc.BillingPostalCode; 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /AccountDeletion.tgr: -------------------------------------------------------------------------------- 1 | trigger AccountDeletion on Account (before delete) { 2 | 3 | // Prevent the deletion of accounts if they have related opportunities. 4 | for (Account a : [SELECT Id FROM Account 5 | WHERE Id IN (SELECT AccountId FROM Opportunity) AND 6 | Id IN :Trigger.old]) { 7 | Trigger.oldMap.get(a.Id).addError( 8 | 'Cannot delete account with related opportunities.' 9 | ); 10 | } 11 | } -------------------------------------------------------------------------------- /AccountHandler.cls: -------------------------------------------------------------------------------- 1 | public class AccountHandler { 2 | //Public method 3 | public static Account insertNewAccount(String name) { 4 | Account acct = new Account(); 5 | acct.Name = name; 6 | try { 7 | insert acct; 8 | } catch(dmlException e) { 9 | return null; 10 | } 11 | return acct; 12 | } 13 | } -------------------------------------------------------------------------------- /AddRelatedRecordTrigger.tgr: -------------------------------------------------------------------------------- 1 | // This trigger adds a related opportunity for each new or updated account 2 | // if no opportunity is already associated with the account. 3 | // The trigger first performs a SOQL query to get all child opportunities 4 | // for the accounts that the trigger fired on. 5 | // The trigger iterates over the list of sObjects in `Trigger.New` to get each account sObject. 6 | // If the account doesn’t have any related opportunity sObjects, the for loop creates one. 7 | // If the trigger created any new opportunities, the final statement inserts them. 8 | trigger AddRelatedRecord on Account(after insert, after update) { 9 | List oppList = new List(); 10 | 11 | // Get the related opportunities for the accounts in this trigger 12 | Map acctsWithOpps = new Map ( 13 | [SELECT Id, (SELECT Id FROM Opportunities) FROM Account WHERE Id IN :Trigger.New] 14 | ); 15 | 16 | // Add an opportunity for each account if it doesn't already have one. 17 | // Iterate through each account. 18 | for(Account a :Trigger.New) { 19 | System.debug('acctsWithOpps.get(a.Id).Opportunities.size()=' + acctsWithOpps.get(a.Id).Opportunities.size()); 20 | 21 | // Check if the account already has a related opportunity. 22 | if (acctsWithOpps.get(a.Id).Opportunities.size() == 0) { 23 | // Check if the account already has a related opportunity. 24 | oppList.add(new Opportunity(Name = a.Name + ' Opportunity', 25 | StageName = 'Prospecting', 26 | CloseDate = System.today().addMonths(1), 27 | AccountId = a.Id)); 28 | } 29 | } 30 | if(oppList.size() > 0) { 31 | insert oppList; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Aura Components/ExpenseController.cls: -------------------------------------------------------------------------------- 1 | public with sharing class ExpensesController { 2 | @AuraEnabled 3 | public static List getExpenses() { 4 | 5 | // Check to make sure all fields are accessible to this user 6 | String[] fieldsToCheck = new String[] { 7 | 'Id', 'Name', 'Amount__c', 'Client__c', 'Date__c', 8 | 'Reimbursed__c', 'CreatedDate' 9 | }; 10 | 11 | Map fieldDescribeTokens = 12 | Schema.SObjectType.Expense__c.fields.getMap(); 13 | 14 | for(String field : fieldsToCheck) { 15 | if( ! fieldDescribeTokens.get(field).getDescribe().isAccessible()) { 16 | throw new System.NoAccessException(); 17 | } 18 | } 19 | 20 | // OK, they're cool, let 'em through 21 | return [SELECT Id, Name, Amount__c, Client__c, Date__c, 22 | Reimbursed__c, CreatedDate 23 | FROM Expense__c]; 24 | } 25 | 26 | @AuraEnabled 27 | public static Expense__c saveExpense(Expense__c expense) { 28 | // Perform isUpdateable() checking first, then 29 | upsert expense; 30 | return expense; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Aura Components/ExpensesController.cls: -------------------------------------------------------------------------------- 1 | public with sharing class ExpensesController { 2 | @AuraEnabled 3 | public static List getExpenses() { 4 | // Check to make sure all fields are accessible to this user 5 | String[] fieldsToCheck = new String[] { 6 | 'Id', 'Name', 'Amount__c', 'Client__c', 'Date__c', 7 | 'Reimbursed__c', 'CreatedDate' 8 | }; 9 | 10 | Map fieldDescribeTokens = 11 | Schema.SObjectType.Expense__c.fields.getMap(); 12 | 13 | for(String field : fieldsToCheck) { 14 | if( ! fieldDescribeTokens.get(field).getDescribe().isAccessible()) { 15 | throw new System.NoAccessException(); 16 | } 17 | } 18 | // OK, they're cool, let 'em through 19 | return [SELECT Id, Name, Amount__c, Client__c, Date__c, 20 | Reimbursed__c, CreatedDate 21 | FROM Expense__c]; 22 | } 23 | } 24 | @AuraEnabled 25 | public static List getExpenses() { 26 | // Perform isAccessible() checking first, then 27 | return [SELECT Id, Name, Amount__c, Client__c, Date__c, 28 | Reimbursed__c, CreatedDate 29 | FROM Expense__c]; 30 | } 31 | 32 | @AuraEnabled 33 | public static Expense__c saveExpense(Expense__c expense) { 34 | // Perform isUpdateable() checking first, then 35 | upsert expense; 36 | return expense; 37 | } 38 | 39 | 40 | public with sharing class ExpensesController { 41 | @AuraEnabled 42 | public static List getExpenses() { 43 | // Perform isAccessible() checking first, then 44 | return [SELECT Id, Name, Amount__c, Client__c, Date__c, 45 | Reimbursed__c, CreatedDate 46 | FROM Expense__c]; 47 | } 48 | 49 | @AuraEnabled 50 | public static Expense__c saveExpense(Expense__c expense) { 51 | // Perform isUpdatable() checking first, then 52 | upsert expense; 53 | return expense; 54 | } 55 | } -------------------------------------------------------------------------------- /Aura Components/README.md: -------------------------------------------------------------------------------- 1 | 2 | ## Components 3 | * Lightning components are supposed to be self-contained. 4 | * They are stand-alone elements that encapsulate all of their essential functionality. 5 | * A component is not allowed to reach into another component, even a child component, and alter its internals. 6 | * There are two principal ways to interact with or affect another component: 7 | * setting attributes on the component’s tag - A component’s public attributes constitute one part of its API. 8 | * The second way to interact with a component is through events. public events constitute a part of the component’s public API. 9 | * `type="toggle"` is really a checkbox with a toggle switch design. 10 | * `class` enables you to apply custom CSS styling or use SLDS utilities. 11 | * `messageToggleActive` and `messageToggleInactive` provides a custom label for the checked and unchecked positions 12 | * `onchange` attribute of gives us an easy way to wire the toggle switch to an action handler that updates the record when you slide right (checked) or slide left (unchecked) 13 | * callback to handle the response 14 | * Components do not reach into other components and set values on them. 15 | 16 | #### clickReimbursed Handler 17 | ```javascript 18 | ({ 19 | clickReimbursed: function(component, event, helper) { 20 | var expense = component.get("v.expense"); 21 | var updateEvent = component.getEvent("updateExpense"); 22 | updateEvent.setParams("expense": expense); 23 | updateEvent.fire(); 24 | } 25 | }) 26 | ``` 27 | * `updateExpense` is a custom event, that is, an event we write ourselves 28 | * You can tell because, unlike getting a server action, we use component.getEvent() instead of component.get(). Also, what we are getting doesn’t have a value provider, just a name. 29 | 30 | 31 | 32 | ## Resources 33 | ### JavaScript 34 | * [JavaScript The Right Way](http://jstherightway.org/) 35 | 36 | ### SLDS 37 | * [SLDS](https://www.lightningdesignsystem.com/) 38 | ### Lightning Components 39 | * [Add Lightning Components as Custom Tabs in the Salesforce App](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/aura_add_cmp_salesforce1.htm) 40 | * [Add Lightning Components as Custom Tabs in a Lightning Experience App](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/aura_add_cmp_lex.htm) 41 | * [Configure Components for Lightning Pages and the Lightning App Builder](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/components_config_for_app_builder.htm) 42 | * [Configure Components for Communities](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/components_config_for_builder.htm) 43 | * [Use Lightning Components in Visualforce Pages](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/components_visualforce.htm) 44 | * [Add Aura Components to Any App with Lightning Out (Beta)](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/lightning_out.htm) 45 | * [Use Aura Components with Flows](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/components_using_flow.htm) 46 | ### Debugging 47 | * [Chrome DevTools](https://developers.google.com/web/tools/chrome-devtools/?utm_source=dcc&utm_medium=redirect&utm_campaign=2018Q2) 48 | * [Salesforce Lightning Inspector Chrome Extension](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/inspector_intro.htm) 49 | * [Lightning Components Debugging](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/debug_intro.htm) 50 | ### Data Types 51 | * [Supported aura:attribute Types](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/ref_aura_attribute.htm) 52 | * [Component Body](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/components_body.htm) 53 | * [Component Facets](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/components_facets.htm) 54 | ### Helpers 55 | * [Sharing JavaScript Code in a Component Bundle](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/js_helper.htm) 56 | * [Using JavaScript](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/js_intro.htm) 57 | ### Server Request Lifecycle and Handling 58 | * [Creating Server-Side Logic with Controllers](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/controllers_server_intro.htm) 59 | * [Calling a Server-Side Action](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/controllers_server_actions_call.htm) 60 | * [Queueing of Server-Side Actions](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/controllers_server_actions_queue.htm) 61 | ### Security 62 | * [Security for Lightning Components](https://trailhead.salesforce.com/en/content/learn/modules/security-for-lightning-components) 63 | * [CRUD and Field-Level Security (FLS)](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/apex_crud_fls.htm) 64 | * [Data Leak Prevention](https://trailhead.salesforce.com/en/content/learn/modules/data-leak-prevention) 65 | ### Application Events 66 | * [Application Events](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/events_application.htm) 67 | * [Communicating with Events](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/events_intro.htm) 68 | * [Events Best Practices](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/events_best_practices.htm) 69 | * [Events Anti-Patterns](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/events_anti_patterns.htm) 70 | ### Bundle Resource Types 71 | * [Component Bundles](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/components_bundle.htm) 72 | * [Providing Component Documentation](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/components_documentation.htm) 73 | * [Client-Side Rendering to the DOM](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/js_renderers.htm) 74 | ### Navigation 75 | * [Navigate Across Your Apps with Page References](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/components_navigation.htm) 76 | * [force:navigateToURL](https://developer.salesforce.com/docs/component-library/bundle/force:navigateToURL/documentation) 77 | ### Dynamically Creating Components 78 | * [Dynamically Creating Components](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/js_cb_dynamic_cmp_async.htm) 79 | ### Error Handling 80 | * [Throwing and Handling Errors](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/js_throw_error.htm) 81 | * [Validating Fields](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/js_validate_fields.htm) 82 | * [Returning Errors from an Apex Server-Side Controller](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/controllers_server_apex_custom_errors.htm) 83 | ### `force:` Namespace Components and Events 84 | 85 | ### System Events 86 | * [System Events](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/events_system.htm) 87 | * [Event Handling Lifecycle](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/events_overview.htm) 88 | * [Events Fired During the Rendering Lifecycle](https://developer.salesforce.com/docs/atlas.en-us.218.0.lightning.meta/lightning/components_lifecycle.htm) 89 | -------------------------------------------------------------------------------- /Aura Components/expenses.cmp.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aura Components/messages.cmp.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 |

Hello Playground

8 |

Silly fun with attributes and expressions.

9 | 10 |

List Items

11 |

12 |

13 |

14 | 15 |

List Iteration

16 | 17 |

18 |
19 | 20 |

Conditional Expressions and Global Value Providers

21 | 22 |

23 | 24 |

25 |
26 |
27 |
28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Aura Components/packItemController.js: -------------------------------------------------------------------------------- 1 | ({ 2 | packItem : function(component, event, handler) { 3 | var btnClicked = event.getSource(); // reference to the button 4 | var btnMessage = btnClicked.get("v.label"); //look inside the button and get its label, which is set on the in the component markup 5 | component.set("v.message", btnMessage); // update our message 6 | } 7 | }) 8 | 9 | // packItem - action handler name 10 | // function() - anonymous function declaration 11 | // (component, event, hanlder) - function signature with 3 parameters 12 | // component—the component 13 | // event—the event that caused the action handler to be called 14 | // helper—the component’s helper, resource of reusable functions 15 | // Inside the event is the notion of the source - the thing that generated the event which is button itself. 16 | // calling `event.getSource()` gets us a reference to the specific 17 | 18 | // Adding {!c.handleClick} to the onclick attribute of a component 19 | // (1) wires it up to the specific action handler. Calling component.set("v.message", newMessage) 20 | // (2) wires up the result of that action handler to the component’s message attribute. 21 | // Which is itself wired up to the {!v.message} expression. 22 | 23 | { 24 | packItem: function(component, event, handler) { 25 | //set the Packed__c property of the item (instance of Camping_Item__c) attribute 26 | component.set("v.item.Packed__c", true); 27 | //event.getSource refers the source tag from the event has invoked. 28 | //set the disabled attribute to true 29 | event.getSource().set("v.disabled", true); 30 | } 31 | } 32 | 33 | // aura:id - It sets a (locally) unique ID on each tag it’s added to, and that ID is how you’ll read values out of the form fields. The fields all share the same ID in this example so that we can access them as an array for field validation. 34 | 35 | createExpense: function(component, expense) { 36 | var action = component.get("c.saveExpense"); 37 | action.setParams({ 38 | "expense": expense 39 | }); 40 | action.setCallback(this, function(response) { 41 | var state = response.getState(); 42 | if (state === "SUCCESS") { 43 | var expenses = component.get("v.expenses"); 44 | expenses.push(response.getReturnValue()); 45 | component.set("v.expenses", expenses); 46 | } 47 | }); 48 | $A.enqueueAction(action); 49 | } 50 | 51 | // 1. create an action (Apex controller method)= var action = component.get("c.saveExpense"); 52 | // 2. Next we attach a data payload to the action. We need to send the data for the new expense up to the server. 53 | // use action.setParams() and provide a JSON-style object with parameter name-parameter value pairs. 54 | // parameter name must match the parameter name used in your Apex method declaration. 55 | // 3. set the callback for the request. - this is what will happen when the server returns a response. 56 | // 4. get() the expenses attribute, push() a value onto it, and then set() it. -------------------------------------------------------------------------------- /AutomaticProperty.cls: -------------------------------------------------------------------------------- 1 | public class AutomaticProperty { 2 | public integer MyReadOnlyProp { get; } 3 | public double MyReadWriteProp { get; set; } 4 | public string MyWriteOnlyProp { set; } 5 | } 6 | 7 | //to call the class use this code: 8 | 9 | /** 10 | AutomaticProperty ap = new AutomaticProperty(); 11 | ap.MyReadOnlyProp = 5; 12 | ap.MyReadWriteProp = 5; 13 | System.assertEquals(5, ap.MyReadOnlyProp); 14 | */ -------------------------------------------------------------------------------- /BasicProperty.cls: -------------------------------------------------------------------------------- 1 | public class BasicProperty { 2 | public integer prop { 3 | get { return prop; } 4 | set { prop = value; } 5 | } 6 | } -------------------------------------------------------------------------------- /Coinbase/Components/onb_SelfRegistrationEntityDetails/onb_SelfRegistrationEntityDetails.cmp.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 28 | 29 |
30 | 31 | 42 |
43 | hello {!v.userId} 44 |
45 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 |
61 | hello {!v.userId} 62 |
63 | 64 |
65 | 66 |
67 | 68 | 69 |
70 | 71 |
72 | 73 |
74 | 75 |
76 | 77 |
78 | 79 | 80 | 81 |
82 | 83 | 84 | 96 | 97 | 98 | 110 | 111 | 118 |
119 | 120 |
121 | 122 |
123 | 124 | 132 | 133 | 134 | 135 |
136 | 137 |
138 | 139 |
140 | 141 | 142 |
143 |
-------------------------------------------------------------------------------- /Coinbase/Picklist.md: -------------------------------------------------------------------------------- 1 | ## Picklist Criteria 2 | * find and convert existing state and country/territory text data into standard picklist values. 3 | * find where state and country/territory data is used in customizations such as reports and list views, because you may need to update them when you enable the picklists. 4 | * Scan for Affected Data and Customizations 5 | 6 | 7 | 8 | * all community and portal users created in a Salesforce org have to be associated with an account, whether they’re business accounts or person accounts. 9 | * enable data protection options in her org 10 | * prep the portal for self-registration 11 | 12 | * page 1 change the a 13 | * turned sharing off for the user 14 | * Salesforce Security Model 15 | * Controllers are handling guest users 16 | * User is able to complete the authentication flow 17 | * application id is not 18 | * Lightning component on the community builder page 19 | * Onboarding Application object 20 | * Record types: Individual and Entity 21 | * Listener built 22 | * 23 | 24 | 25 | ### Onboarding App 26 | * Application for approving new customers 27 | * Docs never expire 28 | * EBA - Enterprise Business Application - Prime Application Portal 29 | * Prime portal 30 | * Customer portal is self service 31 | * No restrictions on the countries 32 | * CBAM - asset management group 33 | * Earn.com got merged into sales 34 | * Prime and Custody are the most important products 35 | * Data service to cache on the client 36 | * Amazon SES filter 37 | * Dave Farmer - head of trading platform 38 | * Samuel - head of custody 39 | 40 | 41 | ## Page Layouts for Onb 2.0 42 | * Advologix Contact Layout 43 | * CBAM Contact Layout 44 | * Contact Layout 45 | * EBA Contact Layout 46 | * Earn.com Contact Layout 47 | * SysAdmin EBA Contact Layout -------------------------------------------------------------------------------- /Coinbase/SelfRegistrationEntityDetails/onb_LightningSelfRegisterController/LIghtningSelfRegisterControllerTest.cls: -------------------------------------------------------------------------------- 1 | @isTest 2 | private class LightningSelfRegisterControllerTest { 3 | 4 | @TestSetup 5 | static void setupData() { 6 | User testUser = TestData.createAccounts(1)[0]; 7 | insert acct; 8 | 9 | 10 | } 11 | 12 | @isTest 13 | static void getTotal() { 14 | Account acct = new Account(Name='TestAccount'); 15 | insert acct; 16 | Contact con = new Contact(LastName = 'Tester2'); 17 | insert con; 18 | con.AccountId = acct.Id; 19 | System.runAs( new User(Id = UserInfo.getUserId()) ) { 20 | UserRole rol = [SELECT Id FROM UserRole WHERE Name = 'CEO']; 21 | UserLicense lic = [SELECT Id FROM UserLicense WHERE Name = 'Customer Community']; 22 | Profile prof = [SELECT Id FROM Profile WHERE UserLicenseId = : license.Id LIMIT 1]; 23 | User comUser = new User( 24 | Alias = 'person', 25 | Email = 'standarduser@coinbase.com', 26 | EmailEncodingKey = 'UTF-8', 27 | FirstName = 'Standard', 28 | LastName = 'Test User', 29 | LanguageLocaleKey = 'en_US', 30 | LocaleSidKey = 'en_US', 31 | ProfileId = prof.Id, 32 | Country = 'United States', 33 | IsActive = true, 34 | ContactId = c.Id, 35 | TimeZoneSidKey = 'America/Los_Angeles', 36 | UserName = 'testUser@coinbase.com' 37 | ); 38 | insert comUser; 39 | } 40 | User cUser = [SELECT Id FROM User WHERE userName = 'testUser@coinbase.com' LIMIT 1]; 41 | System.runAs(cUser) { 42 | //PageReference pageRef = Page.CommunityHome; 43 | onb_LightningSelfRegisterController controller = new onb_LightningSelfRegisterController(); 44 | LightningSelfRegisterControllerTest myTC = new LightningSelfRegisterControllerTest(); 45 | controller = myTC.selfRegister(); 46 | } 47 | } 48 | 49 | @isTest 50 | static void testViewPageAsAdmin() { 51 | 52 | } 53 | } -------------------------------------------------------------------------------- /Coinbase/SelfRegistrationEntityDetails/onb_LightningSelfRegisterController/TestData.cls: -------------------------------------------------------------------------------- 1 | @isTest 2 | public class TestData { 3 | public static List createAccounts(Integer count) { 4 | List accts = new List(); 5 | for (Integer i = 0; i < count; i++) { 6 | accts.add(new Account( 7 | Name = 'Test Account ' + i 8 | )); 9 | } 10 | return accts; 11 | } 12 | 13 | public static List createContacts(Account acct, Integer count) { 14 | List cons = new List(); 15 | for (Integer i = 0; i < count; i++) { 16 | cons.add(new Contact( 17 | AccountId = acct.Id, 18 | FirstName = 'John', 19 | LastName = 'Tester' + i 20 | )); 21 | } 22 | return cons; 23 | } 24 | 25 | public static List createProducts(Product2 product, Integer count) { 26 | List product2 = new List(); 27 | for (Integer i = 0; i < count; i++) { 28 | product2.add(new Product2( 29 | Id = product.Id, 30 | Name = 'TestProduct' + i 31 | )); 32 | } 33 | return product2; 34 | } 35 | 36 | public static User standardUser { 37 | get { 38 | if (standardUser == null) { 39 | List standardUser = 40 | [SELECT Id, Username FROM User WHERE Username = 'standarduser@coinbase.com']; 41 | if (standardUser.size() > 0) { 42 | standardUser = standardUser[0]; 43 | } else { 44 | Id profileId = [SELECT Id FROM Profile WHERE Name = 'Standard User' LIMIT 1].Id; 45 | standardUser = new User( 46 | Alias = 'person', 47 | Email = 'standarduser@coinbase.com', 48 | EmailEncodingKey = 'UTF-8', 49 | FirstName = 'Standard', 50 | LastName = 'Test User', 51 | LanguageLocaleKey = 'en_US', 52 | LocaleSidKey = 'en_US', 53 | ProfileId = profileId, 54 | TimeZoneSidKey = 'America/Los_Angeles' 55 | ); 56 | System.runAs(adminUser) { 57 | insert standardUser; 58 | } 59 | } 60 | } 61 | return standardUser; 62 | } 63 | set; 64 | } 65 | 66 | public static User adminUser { 67 | get { 68 | if (adminUser == null) { 69 | adminUser = [SELECT Id FROM User WHERE Profile.Name = 'System Administrator' LIMIT 1]; 70 | } 71 | return adminUser; 72 | } 73 | set; 74 | } 75 | } -------------------------------------------------------------------------------- /Coinbase/SelfRegistrationEntityDetails/onb_LightningSelfRegisterController/onb_LightningSelfRegisterControllerTest.cls: -------------------------------------------------------------------------------- 1 | @IsTest(SeeAllData = true) 2 | public with sharing class onb_LightningSelfRegisterControllerTest { 3 | 4 | /* Verifies that IsValidPassword method with various password combinations. */ 5 | @IsTest 6 | static void testIsValidPassword() { 7 | System.assert(onb_LightningSelfRegisterController.isValidPassword('password?@12334', 'password?@12334') == true); 8 | System.assert(onb_LightningSelfRegisterController.isValidPassword('password?@12334', 'dummyPassword') == false); 9 | System.assert(onb_LightningSelfRegisterController.isValidPassword('password?@12334', null) == false); 10 | System.assert(onb_LightningSelfRegisterController.isValidPassword(null, 'fakePwd') == false); 11 | } 12 | 13 | @IsTest 14 | static void testSiteAsContainerEnabled() { 15 | System.assertNotEquals(null, onb_LightningSelfRegisterController.siteAsContainerEnabled('https://portaleu1-developer-edition.eu11.force.com')); 16 | } 17 | 18 | /* Verifies the selfRegistration method flow with various invalid inputs */ 19 | @IsTest 20 | static void testSelfRegistration() { 21 | Map < String, String > paramsMap = initializeParams(); 22 | System.assertNotEquals(null, paramsMap); 23 | System.assertEquals(Label.Site.lastname_is_required, onb_LightningSelfRegisterController.selfRegister(paramsMap.get('firstName'), '', paramsMap.get('email'), paramsMap.get('password'), paramsMap.get('confirmPasswordCorrect'), null, paramsMap.get('regConfirmUrl'), null, paramsMap.get('startUrl'), true)); 24 | System.assertEquals(Label.Site.email_is_required, onb_LightningSelfRegisterController.selfRegister(paramsMap.get('firstName'), paramsMap.get('lastName'), '', paramsMap.get('password'), paramsMap.get('confirmPasswordCorrect'), null, paramsMap.get('regConfirmUrl'), null, paramsMap.get('startUrl'), true)); 25 | System.assertEquals(Label.Site.email_is_required, onb_LightningSelfRegisterController.selfRegister(null, paramsMap.get('lastName'), '', null, paramsMap.get('confirmPasswordCorrect'), null, paramsMap.get('regConfirmUrl'), null, paramsMap.get('startUrl'), true)); 26 | System.assertEquals(Label.site.passwords_dont_match, onb_LightningSelfRegisterController.selfRegister(paramsMap.get('firstName'), paramsMap.get('lastName'), paramsMap.get('email'), paramsMap.get('password'), paramsMap.get('confirmPasswordWrong'), null, paramsMap.get('regConfirmUrl'), null, paramsMap.get('startUrl'), true)); 27 | System.assertNotEquals(null, onb_LightningSelfRegisterController.selfRegister(paramsMap.get('firstName'), paramsMap.get('lastName'), '', paramsMap.get('password'), paramsMap.get('confirmPasswordWrong'), null, paramsMap.get('regConfirmUrl'), null, paramsMap.get('startUrl'), false)); 28 | } 29 | 30 | 31 | /* Verifies the selfRegistration flow for valid inputs */ 32 | @IsTest 33 | static void testSelfRegisterWithProperCredentials() { 34 | Map < String, String > paramsMap = initializeParams(); 35 | System.assertEquals(null, onb_LightningSelfRegisterController.selfRegister(paramsMap.get('firstName'), paramsMap.get('lastName'), paramsMap.get('email'), paramsMap.get('password'), paramsMap.get('confirmPasswordCorrect'), null, paramsMap.get('regConfirmUrl'), null, paramsMap.get('startUrl'), true)); 36 | } 37 | 38 | /* Verifies SelfRegistration flow with an accounId that is created within the test */ 39 | @IsTest 40 | static void testSelfRegisterWithCreatedAccount() { 41 | Account acc = new Account(name = 'test acc'); 42 | insert acc; 43 | List < Account > accounts = [SELECT Id FROM Account LIMIT 1]; 44 | System.assert(!accounts.isEmpty(), 'There must be at least one account in this environment!'); 45 | String accountId = accounts[0].Id; 46 | Map < String, String > paramsMap = initializeParams(); 47 | System.assertEquals(null, onb_LightningSelfRegisterController.selfRegister(paramsMap.get('firstName'), paramsMap.get('lastName'), paramsMap.get('email'), paramsMap.get('password'), paramsMap.get('confirmPasswordCorrect'), accountId, paramsMap.get('regConfirmUrl'), null, paramsMap.get('startUrl'), false)); 48 | } 49 | 50 | @IsTest 51 | static void testGetNullExtraFields() { 52 | System.assertEquals(new List < Map < String, Object >> (), onb_LightningSelfRegisterController.getExtraFields(null)); 53 | } 54 | 55 | @IsTest 56 | static void testGetNonEmptyExtraFields() { 57 | System.assertEquals(new List < Map < String, Object >> (), onb_LightningSelfRegisterController.getExtraFields('field1')); 58 | } 59 | 60 | /* Verifies validation of extraFields within the Self Registration flow */ 61 | @IsTest 62 | static void testGetExtraFieldsInSelfRegistration() { 63 | List < Map < String, Object >> fieldlist = new List < Map < String, Object >> (); 64 | Map < String, String > paramsMap = initializeParams(); 65 | Map < String, Object > fieldMap = new Map < String, Object > (); 66 | fieldMap.put('description', 'new field'); 67 | fieldMap.put('fieldPath', 'dummyPath'); 68 | fieldlist.add(fieldMap); 69 | String extraFields = JSON.serialize(fieldlist); 70 | System.assertNotEquals(null, onb_LightningSelfRegisterController.selfRegister(paramsMap.get('firstName'), paramsMap.get('lastName'), paramsMap.get('email'), paramsMap.get('password'), paramsMap.get('confirmPasswordCorrect'), null, paramsMap.get('regConfirmUrl'), extraFields, paramsMap.get('startUrl'), true)); 71 | } 72 | 73 | @IsTest 74 | static void onb_LightningSelfRegisterControllerInstantiation() { 75 | onb_LightningSelfRegisterController controller = new onb_LightningSelfRegisterController(); 76 | System.assertNotEquals(controller, null); 77 | } 78 | 79 | /* Helper method to initialize the parameters required for SelfRegistration. */ 80 | private static Map < String, String > initializeParams() { 81 | Map < String, String > paramsMap = new Map < String, String > (); 82 | String firstName = 'test'; 83 | String lastName = 'User'; 84 | String email = 'testUser@salesforce.com'; 85 | String password = 'testuser123'; 86 | String confirmPasswordCorrect = 'testuser123'; 87 | String confirmPasswordWrong = 'wrongpassword'; 88 | String accountId = 'testuser123'; 89 | String regConfirmUrl = 'http://registration-confirm.com'; 90 | String startUrl = 'http://my.company.salesforce.com'; 91 | paramsMap.put('firstName', firstName); 92 | paramsMap.put('lastName', lastName); 93 | paramsMap.put('email', email); 94 | paramsMap.put('password', password); 95 | paramsMap.put('confirmPasswordCorrect', confirmPasswordCorrect); 96 | paramsMap.put('confirmPasswordWrong', confirmPasswordWrong); 97 | paramsMap.put('accountId', accountId); 98 | paramsMap.put('regConfirmUrl', regConfirmUrl); 99 | paramsMap.put('startUrl', startUrl); 100 | return paramsMap; 101 | } 102 | } -------------------------------------------------------------------------------- /Coinbase/SelfRegistrationEntityDetails/onb_SelfRegistrationEntityDetails.cmp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 | 32 | 43 | 46 | 47 |
48 | 49 |
50 | 51 | 52 |
53 | 54 |
55 | 56 |
57 | 58 |
59 | 60 | 61 |
62 | 63 | 67 | 68 | 69 | 70 | 71 | 72 |
73 | 80 | 81 |
82 | 83 | 87 | 88 | 89 | 90 | 91 | 92 |
93 | 100 |
101 | 102 |
103 | 104 |
105 | 106 | 114 | 115 | 116 | 117 |
118 | 119 |
120 | 121 |
122 | 123 | 124 |
125 |
-------------------------------------------------------------------------------- /Coinbase/SelfRegistrationEntityDetails/onb_SelfRegistrationEntityDetailsHelper.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by joshuakrinsky on 2019-01-29. 3 | */ 4 | ({ 5 | init:function(component){ 6 | var action = component.get("c.init"); 7 | action.setCallback(this, function(response){ 8 | if (response.getState() == "SUCCESS") { 9 | var rtnValue = response.getReturnValue(); 10 | console.log('applicationId = ' + rtnValue); 11 | //component.set('v.userId', response.getReturnValue()); 12 | } 13 | }); 14 | 15 | $A.enqueueAction(action); 16 | }, 17 | getLoggedInUserId:function(component){ 18 | var action = component.get("c.getCurrentUserId"); 19 | action.setCallback(this, function(response){ 20 | if (response.getState() == "SUCCESS") { 21 | component.set('v.userId', response.getReturnValue()); 22 | } 23 | }); 24 | 25 | $A.enqueueAction(action); 26 | }, 27 | getCountries: function (component) { 28 | OnboardingUtils.fetchPickListVals(component, 'Business_Address_Country__c', 'country'); 29 | }, 30 | getProducts: function (component) { 31 | var options = []; 32 | var action = component.get("c.getProducts"); 33 | action.setCallback(this, function(response){ 34 | if (response.getState() == "SUCCESS") { 35 | var allValues = response.getReturnValue(); 36 | for (var i = 0; i < allValues.length; i++) { 37 | options.push({ 38 | class: "optionClass", 39 | label: allValues[i].Name, 40 | value: allValues[i].Id + '::' + allValues[i].Name 41 | }); 42 | } 43 | component.find('products').set("v.options", options); 44 | } 45 | }); 46 | 47 | $A.enqueueAction(action); 48 | 49 | }, 50 | completeRegistration:function(component, event){ 51 | //street 1 52 | var street1 = component.find("street1").get("v.value"); 53 | //street 2 54 | var street2 = component.find("street2").get("v.value"); 55 | //city 56 | var city = component.find("city").get("v.value"); 57 | //country 58 | var country = component.find("country").get("v.value"); 59 | //state 60 | var state = component.find("state").get("v.value"); 61 | //postal code 62 | var postalCode = component.find("postalCode").get("v.value"); 63 | //products 64 | var products = component.find("products").get("v.value"); 65 | var action = component.get("c.completeRegistration"); 66 | action.setParams({ 67 | street1: street1, 68 | street2: street2, 69 | city: city, 70 | state: state, 71 | country:country, 72 | postalCode:postalCode, 73 | products:products 74 | }); 75 | 76 | action.setCallback(this, function(a){ 77 | var rtnValue = a.getReturnValue(); 78 | if (rtnValue !== null) { 79 | component.set("v.errorMessage",rtnValue); 80 | component.set("v.showError",true); 81 | } 82 | }); 83 | 84 | $A.enqueueAction(action); 85 | } 86 | }) -------------------------------------------------------------------------------- /Coinbase/onb_ApplicationFormComponent/onb_ApplicationForm.cmp.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 17 | 18 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
41 | 42 |
43 | 44 |
45 | 46 | 51 | 52 | 53 |
-------------------------------------------------------------------------------- /Coinbase/onb_RegisterEntityDetailsController/onb_RegisterEntityDetailsController.cls: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by joshuakrinsky on 2019-01-29. 3 | */ 4 | 5 | //fixme: make this work with sharing turned on 6 | global with sharing class onb_RegisterEntityDetailsController extends onb_BaseLightningController { 7 | 8 | public onb_RegisterEntityDetailsController(){ 9 | 10 | } 11 | 12 | @AuraEnabled 13 | public static Id getCurrentUserId() { 14 | return UserInfo.getUserId(); 15 | } 16 | 17 | @AuraEnabled 18 | public static List < String > getSelectOptions(sObject objObject, string fld) { 19 | return onb_BaseLightningController.getSelectOptions(objObject, fld); 20 | } 21 | 22 | @AuraEnabled 23 | public static List getProducts(){ 24 | List products = [Select Id, Name from Product2]; 25 | return products; 26 | } 27 | 28 | @AuraEnabled 29 | public static String completeRegistration(Id appId, String street1, String street2, String city, String country, String state, String postalCode, String[] products) { 30 | 31 | System.debug('completeRegistration'); 32 | 33 | Savepoint sp = null; 34 | 35 | try{ 36 | 37 | sp = Database.setSavepoint(); 38 | 39 | Id userId = UserInfo.getUserId(); 40 | User user = [select Id, Contact.AccountId from User where Id = :UserInfo.getUserId()]; 41 | onb_Onboarding_Application__c app = [Select Id, (Select Id from Onboarding_Application_Products__r) from onb_Onboarding_Application__c where Onboarding_Account__c = :user.Contact.AccountId limit 1]; 42 | 43 | app.Business_Address_Line_1__c = street1; 44 | app.Business_Address_Line_2__c = street2; 45 | app.Business_Address_Country__c = country; 46 | app.Business_Address_State__c = state; 47 | app.Business_Address_Postal_Code__c = postalCode; 48 | 49 | //fixme: for dev purposes only 50 | delete app.Onboarding_Application_Products__r; 51 | 52 | update app; 53 | 54 | 55 | List obProducts = new List(); 56 | 57 | String[] pTokens; 58 | Id pId; 59 | String pName; 60 | for(String product : products){ 61 | System.debug('product = ' + product); 62 | product = EncodingUtil.urlDecode(product, 'ASCII'); 63 | System.debug('product after decode = ' + product); 64 | pTokens = product.split('::'); 65 | pId = pTokens[0]; 66 | pName = pTokens[1]; 67 | 68 | System.debug('pId = ' + pId); 69 | System.debug('pName = ' + pName); 70 | 71 | onb_Onboarding_Application_Product__c obProduct = new onb_Onboarding_Application_Product__c( 72 | Onboarding_Application__c = app.Id, 73 | Product__c = pId, 74 | Name = pName 75 | ); 76 | 77 | obProducts.add(obProduct); 78 | } 79 | 80 | Database.insert(obProducts); 81 | 82 | //todo: send account activation/password reset email to user now that they have complete reg 83 | //System.resetPasswordWithEmailTemplate(userId, true, emailTemplateName); 84 | Site.forgotPassword(UserInfo.getUserName(), 'Onboarding_Community_Welcome_Email'); 85 | 86 | PageReference regCompleteRef = new PageReference('./login/CheckPasswordResetEmail'); 87 | 88 | aura.redirect(regCompleteRef); 89 | 90 | } catch (Exception ex) { 91 | 92 | Database.rollback(sp); 93 | System.debug(ex); 94 | return ex.getMessage(); 95 | } 96 | 97 | 98 | return null; 99 | } 100 | } -------------------------------------------------------------------------------- /Coinbase/onb_RegisterEntityDetailsController/onb_RegisterEntityDetailsControllerTest.cls: -------------------------------------------------------------------------------- 1 | @isTest 2 | private class onb_RegisterEntityDetailsControllerTest { 3 | 4 | @TestSetup 5 | static void setupDate() { 6 | Account acct = TestData.createAccounts(1)[0]; 7 | insert acct; 8 | } 9 | 10 | @isTest static void testonb_RegisterEntityDetailsController() { 11 | 12 | } 13 | 14 | @isTest static void testCurrentUserId() { 15 | Id userId = onb_RegisterEntityDetailsController.getCurrentUserId(); 16 | System.assertNotEquals(null, userId); 17 | System.assertNotEquals('', userId); 18 | System.assert(userId != null); 19 | } 20 | 21 | @isTest 22 | static void testSelectedOptions() { 23 | //onb_RegisterEntityDetailsController controller = new onb_RegisterEntityDetailsController(); 24 | List selectOption = onb_RegisterEntityDetailsController.getSelectOptions(); 25 | System.assertEquals(null, controller); 26 | System.assert(controller != null); 27 | } 28 | 29 | @isTest 30 | static void testProducts() { 31 | List product2 = onb_RegisterEntityDetailsController.getProducts(); 32 | System.assertNotEquals(null, product2); 33 | System.assert(product2 != null); 34 | } 35 | 36 | @isTest 37 | static void testInvalidProducts() { 38 | List product2 = onb_RegisterEntityDetailsController.getProducts(); 39 | System.assertEquals('Normal', product2); 40 | } 41 | 42 | @isTest static void testCompleteRegistration() { 43 | Id appId; 44 | String street1; 45 | String street2; 46 | String city; 47 | String country; 48 | String state; 49 | String postalCode; 50 | String[] products; 51 | String completeReg = onb_RegisterEntityDetailsController.completeRegistration(appId, street1, street2, city, country, state, postalCode, products); 52 | User u = [SELECT UserName,Email FROM User LIMIT 1]; 53 | System.assertNotEquals(null, appId); 54 | System.assert(appId != null); 55 | } 56 | 57 | @isTest 58 | 59 | 60 | @isTest 61 | static void testViewPageAsAdmin() { 62 | } 63 | } 64 | // Positive Tests 65 | // 1. set up data 66 | // 2. execute the logic we are testing 67 | // 3. query for updated record 68 | // 4. assert expected result 69 | // Negative Tests 70 | 71 | // Exception Tests (exceptions are thrown as expected) 72 | 73 | // Bulk Tests (everything still works when we are dealing with lots of records) 74 | 75 | /** 76 | Set up test for custom controller: 77 | 1. set the current page 78 | PageReference pageRef = Page.EmployeeBonuses; 79 | Test.setCurrentPage(pageRef); 80 | 81 | 2. set up the controller 82 | EmployeeBonusController ctrl = new EmployeeBonusController(); 83 | 84 | 3. call method(s) in the controller 85 | ctrl.doInit(); 86 | 87 | 4. check the resulting data by referencing the property in the class 88 | List employees = ctrl.employees; 89 | 90 | 5. assert expectations 91 | System.assertEquals(2, ctrl.employees.size(), 'The list should have two employees'); 92 | System.assertEquals(0, ApexPages.getMessages().size(), 'There should be no error messages on the page'); 93 | 94 | 95 | Set up the Lightning Component Controller: 96 | 1. set the current page 97 | PageReference pageRef = Page.EmployeeBonuses; 98 | Test.setCurrentPage(pageRef); 99 | 100 | 2. Call the @AuraEnabled method 101 | List employees = EmployeeBonusController.getEmployeeList(); 102 | 103 | // call method(s) in the controller 104 | ctrl.doInit(); 105 | 106 | // check the resulting data by referencing the property in the class 107 | List employees = ctrl.employees; 108 | 109 | // assert expectations 110 | System.assertEquals(2, ctrl.employees.size(), 'The list should have two employees'); 111 | System.assertEquals(0, ApexPages.getMessages().size(), 'There should be no error messages on the page'); 112 | */ -------------------------------------------------------------------------------- /ContactAndLeadSearch.cls: -------------------------------------------------------------------------------- 1 | public class ContactAndLeadSearch { 2 | public static List> searchContactsAndLeads (String name) { 3 | List> searchList = [FIND 'Vuk OR Smith' IN ALL FIELDS 4 | RETURNING Contact(LastName), Lead(LastName)]; 5 | 6 | return searchList; 7 | } 8 | } -------------------------------------------------------------------------------- /ContactSearch.cls: -------------------------------------------------------------------------------- 1 | public class ContactSearch { 2 | 3 | //this is a method declaration 4 | // Static means that this method is a class method (static method) and not instance method 5 | // For instance method you omit static keyword, but you would need an instance of that class to call the method 6 | // List is return type of the method 7 | // It means that this method will return a 'List' of 'Contact' objects 8 | // searchForContacts is method name, use it to call this method 9 | // String lastname and String mailingPostalCode are parameters that are expected by this method 10 | public static List searchForContacts(String lastName, String mailingPostalCode){ 11 | 12 | List retList = [SELECT Name, LastName, MailingPostalCode 13 | FROM Contact 14 | WHERE LastName = :lastName AND MailingPostalCode = :mailingPostalCode]; 15 | // the above line assigns the results of the query to variable retList 16 | // List retList makes a variable with name retList of type List 17 | // WHERE LastName = :lastName AND MailingPostalCode = :mailingPostalCode --> 18 | // this adds a filter to the query, so that it would only return results which match LastName 19 | // and MailingPostalCode with given parameters 20 | // : --> tells your code that it is not the value to be searched for, but a variable from code 21 | 22 | return retList; 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /ContactSearchV2.cls: -------------------------------------------------------------------------------- 1 | public class ContactSearch { 2 | public static List searchForContacts (String lastName, String mailingPostalCode) { 3 | return [SELECT Name, LastName, MailingPostalCode 4 | FROM Contact 5 | WHERE LastName = :lastName AND MailingPostalCode = :mailingPostalCode]; 6 | } 7 | } -------------------------------------------------------------------------------- /EmailManager.cls: -------------------------------------------------------------------------------- 1 | public class EmailManager { 2 | //public method 3 | public void sendMail(String address, String subject, String body) { 4 | //Create an email message object 5 | Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage(); 6 | String[] toAddresses = new String[] {address}; 7 | mail.setToAddress(toAddresses); 8 | mail.setSubject(subject); 9 | mail.setPlainTextBody(body); 10 | //Pass this email message to the built-in sendMail method of the Messaging class 11 | Messaging.SendEmailResult[] results = Messaging.sendEmail( 12 | new Messaging.SingleEmailMessage[] { mail } 13 | ); 14 | 15 | //Call a helper method to inspect the returned result 16 | //This helper method inspects the results of the email send call and is called by sendMail() 17 | inspectResults(results); 18 | } 19 | 20 | //Helper method 21 | private static Boolean inspectResults(Messaging.SendEmailResult[] results) { 22 | Boolean sendResult = true; 23 | 24 | //sendEmail returns an array of result objects. 25 | //Iterate through the list to inspect results. 26 | //In this class, the methods sent only one email, 27 | //so we should have only one result. 28 | for(Messaging.SendEmailResult res : results) { 29 | if(res.isSuccess()) { 30 | System.debug('Email sent successfully'); 31 | } else { 32 | sendResult = false; 33 | System.debug('The following errors occured: ' + res.getErrors()); 34 | } 35 | } 36 | 37 | return sendResult; 38 | } 39 | } -------------------------------------------------------------------------------- /ExampleClass.cls: -------------------------------------------------------------------------------- 1 | // Top-level (outer) class must be public or global (usually public unless they contain 2 | // a Web Service, then they must be global) 3 | public class ExampleClass { 4 | // static final variable (constant) - outer class level only 5 | private static final Integer MY_INT; 6 | 7 | // Non-final static variable - use this to communicate state across triggers 8 | // within a single request 9 | public static String sharedState; 10 | 11 | // Static method - outer class level-only 12 | public static Integer getInt() { return MY_INT; } 13 | 14 | // Static initialization (can be included where the variable is defined) 15 | static { 16 | MY_INT = 2; 17 | } 18 | 19 | // member variable for outer class 20 | private final String m; 21 | 22 | // Instance initialization block - can be done where the variable is declared, 23 | // or in a constructor 24 | { 25 | m = 'a'; 26 | } 27 | 28 | // Because no constructor is explicitly defined in this outer class, an implicit, 29 | // no-argument, public constructor exists 30 | 31 | // Inner interface 32 | public virtual interface MyInterface { 33 | // No access modifier is necessary for interface methods - these are always 34 | // public or global depending on the interface visibility 35 | void myMethod(); 36 | } 37 | 38 | // Interface extension 39 | interface MySecondInterface extends MyInterface { 40 | Integer method2(Integer i); 41 | } 42 | 43 | // Inner class - because it is virtual it can be extended. 44 | // This class implements an interface that, in turn, extends another interface. 45 | // Consequently the class must implement all methods. 46 | public virtual class InnerClass implements MySecondInterface { 47 | 48 | // Inner member variables 49 | private final String s; 50 | private final String s2; 51 | 52 | 53 | // Inner instance initialization block (this code could be located above) 54 | { 55 | this.s = 'x'; 56 | } 57 | 58 | // Inline initialization (happens after the block above executes) 59 | 60 | } 61 | } -------------------------------------------------------------------------------- /ExampleTrigger.tgr: -------------------------------------------------------------------------------- 1 | Trigger ExampleTrigger2 on Contact (after insert, after delete) { 2 | if (Trigger.isInsert) { 3 | Integer recordCount = Trigger.New.size(); 4 | // Call a utility method from another class 5 | EmailManager.sendMail('vukdukic@gmail.com', 'Trailhead Trigger Tutorial', 6 | recordCount + ' contact(s) were inserted. '); 7 | } else if(Trigger.isDelete) { 8 | // Process after delete 9 | } 10 | } -------------------------------------------------------------------------------- /ExtendedClassExample.cls: -------------------------------------------------------------------------------- 1 | public class OuterClass { 2 | 3 | //static final variable - outer class level only 4 | private static final Integer MY_INT; 5 | 6 | //Non-final static variable - use this to communicate state across triggers 7 | //within a single request. 8 | public static String sharedState; 9 | 10 | //Static method - outer class level only 11 | public static Integer getInt() { return MY_INT; } 12 | 13 | //Static initialization (can be included where the variable is defined) 14 | static { MY_INT = 2; } 15 | 16 | //Member variable for outer class 17 | private final String m; 18 | 19 | 20 | } -------------------------------------------------------------------------------- /Notes.md: -------------------------------------------------------------------------------- 1 | Interest Form 2 | 3 | * System diagnostic error 4 | * Duplicate Management feature in Salesforce 5 | * hard dml errors not seen 6 | * leads are being rolled back? 7 | 8 | 9 | ## API 10 | * Monorail (ruby) - customer data sits 11 | * api key visible in ui layer 12 | * cidc process 13 | * stores in github 14 | * encrypt key 15 | * named credentials 16 | * requirement: different keys needed for different environments 17 | * custom metadata approach 18 | * problem: key is instantiated and stored 19 | 20 | ## Communities Page 21 | * all community and portal users created in a Salesforce org have to be associated with an account, whether they’re business accounts or person accounts. 22 | * Registration Page Configuration - Allow external users to self-register. 23 | * Choose a self-registration page to let users join your community. 24 | * Assign users to a profile and account. 25 | * When you enable public access, Salesforce lets guest users view asset files on public pages by default. Adjust this setting in Administration | Preferences. 26 | -------------------------------------------------------------------------------- /PassNonPrimitiveTypeExample.cls: -------------------------------------------------------------------------------- 1 | // List argument is passed by reference into the reference() method and is modified 2 | // in the referenceNew() method, that the List argument can’t be changed to point to another List object. 3 | public class PassNonPrimitiveTypeExample { 4 | // createTemperatureHistory method creates a variable, fillMe, that is a List of Integers and passes it to a method. 5 | public static void createTemperatureHistory() { 6 | List fillMe = new List(); 7 | // The called method fills this list with Integer values representing rounded temperature values. 8 | reference(fillMe); 9 | // The list is modified and contains five items 10 | // as expected. 11 | // When the method returns, an assert statement verifies that the contents of the original 12 | // List variable has changed and now contains five values. 13 | System.assertEquals(fillMe.size(), 5); 14 | 15 | List createMe = new List(); 16 | // The called method assigns the passed-in argument to a newly created List that contains new Integer values. 17 | referenceNew(createMe); 18 | // When the method returns, the original createMe variable doesn’t 19 | // point to the new List but still points to the original List, which is empty. 20 | // The list is not modified because it still points 21 | // to the original list, not the new list 22 | // that the method created. 23 | // An assert statement verifies that createMe contains no values. 24 | System.assertEquals(createMe.size(), 0) 25 | } 26 | 27 | // The called method fills this list with Integer values representing rounded temperature values. 28 | public static void reference(List m) { 29 | // Add rounded temperatures for the last five days. 30 | m.add(70); 31 | m.add(68); 32 | m.add(75); 33 | m.add(80); 34 | m.add(82); 35 | } 36 | 37 | public static void referenceNew(List m) { 38 | // Assign argument to a new List of 39 | // five temperature values. 40 | m = new List{5, 59, 62, 60, 63}; 41 | } 42 | } -------------------------------------------------------------------------------- /PassPrimitiveTypeExample.cls: -------------------------------------------------------------------------------- 1 | public class PassPrimitiveTypeExample { 2 | public static void debugStatusMessage() { 3 | String msg = 'Original Value'; 4 | processString(msg); 5 | // The value of the msg variable didn't 6 | // change; it is still the old value. 7 | System.assertEquals(msg, 'Original Value'); 8 | } 9 | 10 | public static void processString(String s) { 11 | s = 'Modified Value'; 12 | } 13 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | * [Object-Oriented Programming Concepts](http://java.sun.com/docs/books/tutorial/java/concepts/index.html) 3 | * [Access Modifiers](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_access_modifiers.htm) 4 | * [Lightning Picklist Component](https://naveendhanaraj.wordpress.com/2018/06/19/lightning-picklist-component/) 5 | 6 | 7 | * The `global` access modifier, which is more permissive than the `public` modifier and allows access across namespaces and applications. 8 | 9 | ## List 10 | You can add elements to a list when creating the list, or after creating the list by calling the add() method. 11 | * lists don’t require you to determine ahead of time how many elements you need to allocate. 12 | * You can add elements to a list when creating the list, or after creating the list by calling the add() method. 13 | * List elements can be read by specifying an index between square brackets 14 | * you can use the get() method to read a list element. 15 | * Create a list and add elements to it: 16 | ```apex 17 | List colors = new List {'red', 'blue'}; 18 | 19 | //Add elements to list after it has been created 20 | List moreColors = new List(); 21 | moreColors.add('orange'); 22 | 23 | ``` 24 | * List syntax: `List variable name = new List();` 25 | 26 | * List elements can be read by specifying an index between square brackets, just like with array elements. Also, you can use the get() method to read a list element. 27 | 28 | ```apex 29 | // Get elements from a list 30 | String color1 = moreColors.get(0); 31 | String color2 = moreColors[0]; 32 | System.assertEquals(color1, color2); 33 | 34 | //iterate over a list to read elements 35 | for(Integer i=0; imethod definition. 334 | 335 | ##### `@isTest` annotation 336 | * Use the `@isTest` annotation to define classes and methods that only contain code used for testing your application. 337 | * The `@isTest` annotation on methods is equivalent to the `testMethod` keyword. 338 | * `@isTest` annotation can take multiple modifiers within parentheses and separated by blanks. 339 | 340 | * 75% of Apex code must be covered by tests, and all those tests must pass. 341 | * code coverage is a requirement for deployment 342 | * test the common use cases in your app, 343 | * including positive and negative test cases, 344 | * and bulk and single-record processing 345 | * Test methods take no arguments 346 | * The visibility of a test method doesn’t matter 347 | * testing framework is always able to access test methods 348 | * For this reason, the access modifiers are omitted in the syntax. 349 | * Test methods must be defined in test classes, which are classes annotated with isTest 350 | * Test classes can be either private or public. 351 | * If you’re using a test class for unit testing only, declare it as private. 352 | * The verifications are done by calling the `System.assertEquals()` method, which takes two parameters: 353 | * the first is the expected value, and 354 | * the second is the actual value. 355 | 356 | * private access member variable 357 | * private inner class 358 | * private method 359 | * private custom exception 360 | * `@TestVisible` - private or protectd members can be accessed by test methods and only code running in test context. 361 | * 362 | 363 | ## Schema Namespace 364 | A namespace is a declarative region that provides a scope to the identifiers (the names of types, functions, variables, etc) inside it. Namespaces are used to organize code into logical groups and to prevent name collisions that can occur especially when your code base includes multiple libraries. 365 | 366 | ## Static and Instance Methods, Variables, and Initialization Code 367 | ### Using Instance Methods and Variables 368 | * Instance methods and member variables are used by an instance of a class, that is, by an object. 369 | * An instance member variable is declared inside a class, but not within a method. 370 | * Instance methods usually use instance member variables to affect the behavior of the method. 371 | * A class static variable can’t be accessed through an instance of that class. 372 | * If class MyClass has a static variable `myStaticVariable`, and `myClassInstance` is an instance of `MyClass`, `myClassInstance.myStaticVariable` is not a legal expression. 373 | * The same is true for instance methods. If `myStaticMethod()` is a static method, `myClassInstance.myStaticMethod()` is not legal. 374 | * Instead, refer to those static identifiers using the class: `MyClass.myStaticVariable` and `MyClass.myStaticMethod()`. 375 | * An inner class behaves like a static Java inner class, but doesn’t require the static keyword. 376 | ### Using Initialization Code 377 | 378 | 379 | ### Constants 380 | Apex constants are variables whose values do not change after being initialized once. Constants can be defined using the `final` keyword. 381 | The `final` keyword means that the variable can be assigned at most once, either in the declaration itself, or with a static initializer method if the constant is defined in a class. 382 | * This example declares two constants. The first is initialized in the declaration statement. The second is assigned a value in a static block by calling a static method. 383 | ```apex 384 | public class myClass { 385 | static final Integer PRIVATE_INT_CONST = 220; 386 | static final Integer PRIVATE_INT_CONST2; 387 | 388 | public static Integer calculate() { 389 | return 2 + 7; 390 | } 391 | 392 | static { 393 | PRIVATE_INT_CONST2 = calculate; 394 | } 395 | } 396 | ``` 397 | 398 | ### Classes 399 | * `virtual` - definition modifier declares that this class allows extension and overrides. You cannot override a method with the `override` keyword unless the class has been defined as `virtual` 400 | * `abstract` - definition modifier declares that this class contains abstract methods - methods that only have their signature declared and no body defined. 401 | * a class can implement multiple interfaces but only extend one existing class. Apex does not support multiple inheritance 402 | * use `void` if method does not return a value 403 | * Class variable and class methods 404 | * Passed into methods by value: primitive data types 405 | * Passed into methods by reference: non-primitive data types 406 | 407 | ### 408 | * This example shows how a List argument is passed by reference into the `reference()` method and is modified 409 | * It then shows, in the referenceNew() method, that the List argument can’t be changed to point to another List object. 410 | * 1-- the createTemperatureHistory method creates a variable, fillMe, that is a List of Integers and passes it to a method. 411 | 412 | ```Apex 413 | public class PassNonPrimitiveTypeExample { 414 | 415 | } 416 | ``` 417 | ### Static and Instance Methods, Variables, and Initialization Code 418 | Apex classes cannot be static. 419 | * Static methods 420 | * associated with a class 421 | * allowed only in outer classes 422 | * Initialized only when a class is loaded 423 | * ARE NOT transmitted as part of the view state for a Visualforce page 424 | * Static Variables 425 | * associated with a class 426 | * allowed only in outer classes 427 | * Initialized only when a class is loaded 428 | * ARE NOT transmitted as part of the view state for a Visualforce page 429 | * Static Initialization code 430 | * associated with a class 431 | * allowed only in outer classes 432 | * Initialized only when a class is loaded 433 | * ARE NOT transmitted as part of the view state for a Visualforce page 434 | * Instance methods 435 | * associated with a particular object 436 | * have no definition modifier 437 | * created with every object instantiated from the class in which they are created 438 | * Instance Member Variables 439 | * associated with a particular object 440 | * have no definition modifier 441 | * created with every object instantiated from the class in which they are created 442 | * Instance Initialization code 443 | * associated with a particular object 444 | * have no definition modifier 445 | * created with every object instantiated from the class in which they are created 446 | * Local Variables 447 | * associated with a block of code in which they are declared 448 | * must be initialized before they are used 449 | #### Using Static Methods and Variables 450 | * You can use static methods and variables only with outer classes. 451 | * Inner classes have no static methods or variables. 452 | * A static method or variable doesnt require an instance of a class to run 453 | * Before an object of a class is created, all static member variables in a class are initialized, and all static initialization code blocks are executed. 454 | * These items are handled in the order in which they appear in the class 455 | * A static method is used as a utlitiy method, and it never depends on the value of an instance member variable. 456 | * Because a static method is only associated with a class, it cant access the instance member variable values of its class 457 | * static variable is static only within the scope of the Apex transaction. 458 | * it is not static across the server or the entire organization 459 | * the value of a static variable persists within the context of a single transaction and is reset across transaction boundaries 460 | * `to information that is shared across instances of a class, use a static variable` 461 | * all instances of the same class share a single copy of the static variable 462 | * all triggers that a single transaction spawns can communicate with each other by viewing and updating static variables in a related class 463 | * a recursive trigger can use the value of a class variable to determine when to exit the recursion 464 | * define the static variables in a class so that the trigger can access these class member variables and check their static values 465 | * a class static variable cant be accessed through an instance of that class. 466 | ```apex 467 | // MyClass has a static variable = myStaticVariable 468 | // myClassInstance is an instance of MyClass 469 | myClassInstance.myStaticVariable // not a legal expression 470 | MyClass.myStaticVariable // legal 471 | MyClassInstance.myStaticMethod() // not a legal expression 472 | MyClass.myStaticMethod() // legal 473 | ``` 474 | * local variable names are evaluated before class names. 475 | 476 | ### Using Instance Methods and Variables 477 | Instance methods and member variables are used by an instance of a class, object. 478 | * an instance member variable is declared inside a class, but not within a method 479 | * instance methods usually use instance member variables to affect the behavior of a method 480 | 481 | ```apex 482 | public class Plotter { 483 | // This inner class manages the points 484 | class Point { 485 | Double x; 486 | Double y; 487 | 488 | Point(Double x, Double y) { 489 | this.x = x; 490 | this.y = y; 491 | } 492 | Double getXCoordinate() { 493 | return x; 494 | } 495 | Double getYCoordinate() { 496 | return y; 497 | } 498 | } 499 | 500 | List points = new List(); 501 | 502 | public void plot(Double x, Double y) { 503 | points.add(new Point(x, y)); 504 | } 505 | 506 | // The followting method takes the list of points and does somethin 507 | public void render() { 508 | 509 | } 510 | } 511 | ``` 512 | * The instance initialization code in a class is executed each time an object is instantiated from that class. 513 | * These code blocks run before the constructor. 514 | * static initialization block runs only once, regardless of how many times you access the class that contains it. 515 | * Static initialization code is a block of code preceded with the keyword `static`. 516 | * The code blocks are executed in the order in which they appear in the file 517 | * You can use static initialization code to initialize static final variables and to declare information that is static, such as a map of values. 518 | 519 | ### Apex Properties 520 | An Apex property is similar to a variable; however, you can do additional things in your code to a property value before it is accessed or returned. 521 | * Properties can be used to validate data before a change is made 522 | * to prompt an action when data is changed 523 | * to expose data that is retrieved from some other source (such as another class). 524 | * Property definitions include one or two code blocks, representing a get accessor and a set accessor: 525 | * The code in a get accessor executes when the property is read. 526 | * The code in a set accessor executes when the property is assigned a new value. 527 | * If a property has only a get accessor, it is considered read only. 528 | * If a property has only a set accessor, it is considered write only. 529 | * A property with both accessors is considered read-write. 530 | * To declare a property, use the following syntax in the body of a class: 531 | ```apex 532 | Public class BasicClass { 533 | 534 | // Property declaration 535 | access_modifier return_type property_name { 536 | get { 537 | // Get accessor code block 538 | } 539 | set { 540 | // Set accessor code block 541 | } 542 | } 543 | } 544 | ``` 545 | * access_modifier is the access modifier for the property. The access modifiers that can be applied to properties include: `public`, `private`, `global`, and `protected`. In addition, these definition modifiers can be applied: `static` and `transient`. 546 | * `return_type` is the type of the property, such as `Integer`, `Double`, `sObject`, and so on. 547 | ```apex 548 | public class BasicProperty { 549 | public Integer prop { 550 | get { return prop; } 551 | set { prop = value; } 552 | } 553 | } 554 | ``` 555 | Call the `BasicProperty` class: 556 | ```apex 557 | BasicProperty bp = new BasicProperty(); 558 | bp.prop = 5; // calls set accessor 559 | System.assertEqual(5, bp.prop); // calls get accessor 560 | ``` 561 | * The body of the get accessor is similar to that of a method. 562 | * It must return a value of the property type. 563 | * Executing the get accessor is the same as reading the value of the variable. 564 | * The get accessor must end in a return statement. 565 | * We recommend that your get accessor not change the state of the object that it is defined on. 566 | * The set accessor is similar to a method whose return type is void. 567 | * When you assign a value to the property, the set accessor is invoked with an argument that provides the new value. 568 | * When the set accessor is invoked, the system passes an implicit argument to the setter called value of the same data type as the property. 569 | * Properties cannot be defined on `interface`. 570 | * Properties provide storage for values directly. 571 | * You do not need to create supporting members for storing values. 572 | * Properties do not require additional code in their get or set accessor code blocks. 573 | * The following example creates three automatic properties: 574 | ```apex 575 | public class AutomaticProperty { 576 | public integer MyReadOnlyProperty { get; } 577 | public double MyReadWriteProperty { get; set; } 578 | public string MyWriteOnlyProperty { set; } 579 | } 580 | // calling this class: 581 | AutomaticProperty ap = new AutomaticProperty(); 582 | ap.MyReadOnlyProperty = 5; // this produces a compile error: not writable 583 | ap.MyReadWriteProperty = 5; // No error 584 | System.assertEquals(5, MyWriteOnlyProperty); // This produces a compile error: not readable 585 | ``` 586 | 587 | ### Using Static Properties 588 | When a property is declared as `static`, the property's accessor methods execute in a static context. 589 | * accessors do not have access to non-static member variables defined in the class. 590 | ```apex 591 | public class StaticProperty { 592 | private static integer StaticMember; 593 | private integer NonStaticMember; 594 | 595 | // The following produces a system error 596 | // public static integer MyBadStaticProp { return NonStaticMember; } 597 | 598 | public static integer MyGoodStaticProperty { 599 | get { return StaticMember; } 600 | set { StaticMember = value; } 601 | } 602 | 603 | public integer MyGoogNonStaticProperty { 604 | get { return NonStaticMember; } 605 | set { NonStaticMember = value; } 606 | } 607 | } 608 | 609 | // call the instance and static properties 610 | StaticProperty sp = new StaticProperty(); 611 | // The following produces a system error: a static variable cannot be 612 | // accessed through an object instance 613 | // sp.MyGoodStaticProp = 5; 614 | // The following does not produce an error 615 | StaticProperty.MyGoodStaticProp = 5; 616 | ``` 617 | ### Using Access Modifiers on Property Accessors 618 | Property accessors can be defined with their own access modifiers. 619 | * If an accessor includes its own access modifier, this modifier overrides the access modifier of the property. 620 | * The access modifier of an individual accessor must be more restrictive than the access modifier on the property itself. 621 | ```apex 622 | global virtual class PropertyVisibility { 623 | // X is private for read and public for write 624 | public integer X { private get; set; } 625 | // Y can be globally read but only written within a class 626 | global integer Y { get; public set; } 627 | // Z can be read within the class but only subclasses can set it 628 | public integer Z { get; protected set; } 629 | } 630 | ``` 631 | ### Extending a Class 632 | A class that extends another class inherits all the methods and properties of the extended class. 633 | * the extending class can override the existing virtual methods by using the override keyword in the method definition. 634 | * Overriding a virtual method allows you to provide a different implementation for an existing method. 635 | * This means that the behavior of a particular method is different based on the object you’re calling it on. This is referred to as polymorphism. 636 | * A class extends another class using the extends keyword in the class definition. 637 | * A class can only extend one other class, but it can implement more than one interface. 638 | -------------------------------------------------------------------------------- /SOQL.cls: -------------------------------------------------------------------------------- 1 | /** 2 | * To include SOQL queries within your Apex code, wrap the SOQL statement within square brackets and assign 3 | * the return value to an array of sObjects. 4 | * SOQL and SOSL statements in Apex can reference Apex code variables and expressions if they’re preceded by a colon (:). 5 | * This use of a local code variable within a SOQL or SOSL statement is called a bind. 6 | * The Apex parser first evaluates the local variable in code context before executing the SOQL or SOSL statement. 7 | */ 8 | Account[] accts = [SELECT Name, Phone FROM Account]; 9 | 10 | //Add an account and related contact 11 | Account acct = new Account( 12 | Name = 'Crowdart', 13 | Phone = '415-635-9877', 14 | NumberOfEmployees = 50, 15 | BillingCity = 'San Francisco' 16 | ); 17 | 18 | insert acct; 19 | 20 | //Once the account is inserted, the sObject will be populated with an Id. 21 | //Get this Id. 22 | ID acctID = acct.ID; 23 | 24 | Contact con = new Contact( 25 | FirstName='Carol', 26 | LastName='Ruiz', 27 | Phone='(415)555-1212', 28 | Department='Wingo', 29 | AccountId=acctID); 30 | insert con; 31 | // Add account with no contact 32 | Account acct2 = new Account( 33 | Name='The SFDC Query Man', 34 | Phone='(310)555-1213', 35 | NumberOfEmployees=50, 36 | BillingCity='Los Angeles', 37 | Description='Expert in wing technologies.'); 38 | insert acct2; 39 | 40 | Account[] accts = [SELECT Name,Phone FROM Account]; 41 | SELECT Name,Phone FROM Account 42 | SELECT fields FROM ObjectName [WHERE Condition] 43 | SELECT Name,Phone FROM Account 44 | SELECT Name,Phone FROM Account WHERE Name='SFDC Computing' 45 | SELECT Name,Phone FROM Account WHERE (Name='SFDC Computing' AND NumberOfEmployees>25) 46 | SELECT Name,Phone FROM Account WHERE (Name='SFDC Computing' OR (NumberOfEmployees>25 AND BillingCity='Los Angeles')) 47 | WHERE Name LIKE 'SFDC%' 48 | SELECT Name,Phone FROM Account ORDER BY Name 49 | SELECT Name,Phone FROM Account ORDER BY Name ASC 50 | SELECT Name,Phone FROM Account ORDER BY Name DESC 51 | Account oneAccountOnly = [SELECT Name,Phone FROM Account LIMIT 1]; 52 | SELECT Name,Phone FROM Account 53 | WHERE (Name = 'SFDC Computing' AND NumberOfEmployees>25) 54 | ORDER BY Name 55 | LIMIT 10 56 | 57 | Account[] accts = [SELECT Name,Phone FROM Account 58 | WHERE (Name='SFDC Computing' AND NumberOfEmployees>25) 59 | ORDER BY Name 60 | LIMIT 10]; 61 | System.debug(accts.size() + ' account(s) returned.'); 62 | // Write all account array info 63 | System.debug(accts); 64 | 65 | // Accessing Variables in SOQL Queries: 66 | // SOQL statements in Apex can reference Apex code variables and expressions if they are preceded by a colon (:) 67 | // The use of a local variable within a SOQL statement is called a bind. 68 | String targetDepartment = 'Wingo'; 69 | Contact[] techContacts = [SELECT FirstName,LastName 70 | FROM Contact WHERE Department=:targetDepartment]; 71 | 72 | // To get child records related to a parent record, add an inner query for the child records. 73 | // The FROM clause of the inner query runs against the relationship name, rather than a Salesforce object name. 74 | Account[] acctsWithContacts = [SELECT Name, (SELECT FirstName,LastName FROM Contacts) 75 | FROM Account 76 | WHERE Name = 'SFDC Computing']; 77 | // Get child records 78 | Contact[] cts = acctsWithContacts[0].Contacts; 79 | System.debug('Name of first associated contact: ' 80 | + cts[0].FirstName + ', ' + cts[0].LastName); 81 | 82 | Contact[] cts = [SELECT Account.Name FROM Contact 83 | WHERE FirstName = 'Carol' AND LastName='Ruiz']; 84 | Contact carol = cts[0]; 85 | String acctName = carol.Account.Name; 86 | System.debug('Carol\'s account name is ' + acctName); 87 | 88 | // By using SOQL for loops, you can avoid hitting the heap size limit. 89 | // SOQL `for` loops iterate over all of the sObject records returned by a SOQL query. 90 | for (variable : [soql_query]) { 91 | code_block 92 | } 93 | 94 | for (variable_list : [soql_query]) { 95 | code_block 96 | } 97 | 98 | // Both variable and variable_list must be of the same type as the sObjects that are returned by the soql_query 99 | 100 | insert new Account[]{new Account(Name = 'for loop 1'), 101 | new Account(Name = 'for loop 2'), 102 | new Account(Name = 'for loop 3')}; 103 | // The sObject list format executes the for loop once per returned batch 104 | // of records 105 | Integer i=0; 106 | Integer j=0; 107 | for (Account[] tmp : [SELECT Id FROM Account WHERE Name LIKE 'for loop _']) { 108 | j = tmp.size(); 109 | i++; 110 | } 111 | System.assertEquals(3, j); // The list should have contained the three accounts 112 | // named 'yyy' 113 | System.assertEquals(1, i); // Since a single batch can hold up to 200 records and, 114 | // only three records should have been returned, the 115 | // loop should have executed only once 116 | 117 | 118 | List aa = [SELECT Id, Name FROM Account WHERE Name = 'Acme']; 119 | //From this list access individual elements: 120 | if (!aa.isEmpty) { 121 | //.... 122 | } 123 | 124 | //create new object from existing query 125 | Contact c = new Contact(Account = [SELECT Name FROM Account 126 | WHERE NumberOfEmployees > 10 LIMIT 1]); 127 | c.FirstName = 'James'; 128 | c.LastName = 'Joyce'; 129 | 130 | // The count method can be used to return the number of rows returned by a query. 131 | // The following example returns the total number of contacts with the last name of Weissman: 132 | Integer i = [SELECT COUNT() FROM Contact WHERE LastName = 'Weissman']; 133 | -------------------------------------------------------------------------------- /SOSLApexExampls.cls: -------------------------------------------------------------------------------- 1 | List> searchList = [FIND 'Wingo OR SFDC' IN ALL FIELDS 2 | RETURNING Account(Name),Contact(FirstName,LastName,Department)]; 3 | Account[] searchAccounts = (Account[])searchList[0]; 4 | Contact[] searchContacts = (Contact[])searchList[1]; 5 | System.debug('Found the following accounts.'); 6 | for (Account a : searchAccounts) { 7 | System.debug(a.Name); 8 | } 9 | System.debug('Found the following contacts.'); 10 | for (Contact c : searchContacts) { 11 | System.debug(c.LastName + ', ' + c.FirstName); 12 | } -------------------------------------------------------------------------------- /SiteRegisterController/SiteRegisterController.cls: -------------------------------------------------------------------------------- 1 | /** 2 | * An Apex class that creates a portal user 3 | */ 4 | public class SiteRegisterController { 5 | // PORTAL_ACCOUNT_ID is the account on which the contact will be created on 6 | // and then enabled as a portal user. 7 | // Enter the account ID in place of below. 8 | private static Id PORTAL_ACCOUNT_ID = 'id.....'; 9 | 10 | public SiteRegisterController() { 11 | 12 | } 13 | 14 | public String username {get; set;} 15 | public String email {get; set;} 16 | public String password {get: set {} } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /Testing Apex/CentralizeObjectInitialization.cls: -------------------------------------------------------------------------------- 1 | public class CentralizeObjectInitialization { 2 | 3 | } -------------------------------------------------------------------------------- /Testing Apex/CommunityHomeControllerTest.cls: -------------------------------------------------------------------------------- 1 | @isTest 2 | public class CommunityHomeControllerTest { 3 | @isTest static void getTotalReports(){ 4 | Account a = new Account(Name='Test Account Name'); 5 | insert a; 6 | Contact c = new Contact(LastName = 'Contact Last Name'); 7 | c.AccountId = a.Id; 8 | insert c; 9 | System.runAs ( new User(Id = UserInfo.getUserId()) ) { 10 | UserRole r = [select id from UserRole where name = 'CEO']; 11 | UserLicense licence = [SELECT Id FROM UserLicense where name ='Partner Community']; 12 | 13 | Profile p = [SELECT Id FROM Profile WHERE UserLicenseId = : licence.Id Limit 1]; 14 | User comUser = new User(alias = 'test123', email='test123@noemail.com', 15 | emailencodingkey='UTF-8', lastname='Testing', languagelocalekey='en_US', 16 | localesidkey='en_US', profileid = p.Id, country='United States',IsActive =true, 17 | contactId=c.Id, 18 | timezonesidkey='America/Los_Angeles', username='newone@noemail.com'); 19 | insert comuser; 20 | } 21 | User cuser = [select id from user where username ='newone@noemail.com' limit 1]; 22 | System.RunAs(cuser) { 23 | PageReference pageRef = Page.CommunityHome; 24 | Test.setCurrentPage(pageRef); 25 | CommunityHomeController controller = new CommunityHomeController(); 26 | controller.getParentAccounts(); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /Testing Apex/DiagnosticsMain.cls: -------------------------------------------------------------------------------- 1 | public class DiagnosticsMain { 2 | 3 | } -------------------------------------------------------------------------------- /Testing Apex/DiagnosticsMainTest.cls: -------------------------------------------------------------------------------- 1 | @isTest 2 | public class DiagnosticsMainTest { 3 | @isTest 4 | static void TestFakeException() { 5 | DiagnosticsMain.FakeException = true; 6 | List ops = 7 | CreateOpportunities('optest', 8 | NumberOfStageUpdateOpportunities); 9 | 10 | for(Opportunity op : ops) { 11 | op.CloseDate = Date.Today().addDays(5); 12 | op.StageName = 'Prospecting'; 13 | } 14 | 15 | List dbg = [Select ID FROM DebugInfo__c]; 16 | System.Assert(dbg.size()>0); 17 | 18 | Test.StartTest(); 19 | insert ops; 20 | Test.StopTest(); 21 | } 22 | } -------------------------------------------------------------------------------- /Testing Apex/SampleTest.cls: -------------------------------------------------------------------------------- 1 | @isTest 2 | private class SampleTest { 3 | @TestSetup 4 | static void setup() { 5 | // insert sample data that you want for all test methods here 6 | 7 | } 8 | 9 | // use the comments to describe the scenario that you are testing 10 | @isTest 11 | static void testSomething(){ 12 | // set up test data for this scenario 13 | 14 | // execute the logic you are testing 15 | 16 | // query for the updated record(s) 17 | 18 | // assert expected result 19 | 20 | } 21 | } -------------------------------------------------------------------------------- /Testing Apex/VisibleSampleClass.cls: -------------------------------------------------------------------------------- 1 | public class VisibleSampleClass { 2 | // Private member variable 3 | 4 | } -------------------------------------------------------------------------------- /Testing Apex/onb_RegisterEntityDetailsControllerTest.cls: -------------------------------------------------------------------------------- 1 | @isTest 2 | private class onb_RegisterEntityDetailsControllerTest { 3 | 4 | @TestSetup 5 | static void setupDate() { 6 | Account acct = TestData.createAccounts(1)[0]; 7 | insert acct; 8 | } 9 | 10 | @isTest static void testonb_RegisterEntityDetailsController() { 11 | 12 | } 13 | 14 | @isTest static void testCurrentUserId() { 15 | Id userId = onb_RegisterEntityDetailsController.getCurrentUserId(); 16 | System.assertNotEquals(null, userId); 17 | System.assertNotEquals('', userId); 18 | System.assert(userId != null); 19 | } 20 | 21 | @isTest 22 | static void testSelectedOptions() { 23 | //onb_RegisterEntityDetailsController controller = new onb_RegisterEntityDetailsController(); 24 | List selectOption = onb_RegisterEntityDetailsController.getSelectOptions(); 25 | System.assertEquals(null, controller); 26 | System.assert(controller != null); 27 | } 28 | 29 | @isTest 30 | static void testProducts() { 31 | List product2 = onb_RegisterEntityDetailsController.getProducts(); 32 | System.assertNotEquals(null, product2); 33 | System.assert(product2 != null); 34 | } 35 | 36 | @isTest 37 | static void testInvalidProducts() { 38 | List product2 = onb_RegisterEntityDetailsController.getProducts(); 39 | System.assertEquals('Normal', product2); 40 | } 41 | 42 | @isTest static void testCompleteRegistration() { 43 | Id appId; 44 | String street1; 45 | String street2; 46 | String city; 47 | String country; 48 | String state; 49 | String postalCode; 50 | String[] products; 51 | String completeReg = onb_RegisterEntityDetailsController.completeRegistration(appId, street1, street2, city, country, state, postalCode, products); 52 | User u = [SELECT UserName,Email FROM User LIMIT 1]; 53 | System.assertNotEquals(null, appId); 54 | System.assert(appId != null); 55 | } 56 | 57 | @isTest 58 | static void testIncompleteRegistration() { 59 | String completeReg = onb_RegisterEntityDetailsController.completeRegistration('00300000003T2PGAA0', '', 'street2', 'city', 'country', 'California', '', 'products'); 60 | 61 | } 62 | 63 | @isTest static void getTotalReports(){ 64 | Account a = new Account(Name='Test Account Name'); 65 | insert a; 66 | Contact c = new Contact(LastName = 'Contact Last Name'); 67 | c.AccountId = a.Id; 68 | insert c; 69 | System.runAs ( new User(Id = UserInfo.getUserId()) ) { 70 | UserRole r = [select id from UserRole where name = 'CEO']; 71 | UserLicense licence = [SELECT Id FROM UserLicense where name = 'Partner Community']; 72 | Profile p = [SELECT Id FROM Profile WHERE UserLicenseId = : licence.Id Limit 1]; 73 | User comUser = new User(alias = 'test123', 74 | email='test123@noemail.com', 75 | emailencodingkey='UTF-8', 76 | lastname='Testing', 77 | languagelocalekey='en_US', 78 | localesidkey='en_US', 79 | profileid = p.Id, 80 | country='United States', 81 | IsActive =true, 82 | contactId=c.Id, 83 | timezonesidkey='America/Los_Angeles', 84 | username='newone@noemail.com'); 85 | insert comuser; 86 | } 87 | User cuser = [select id from user where username ='newone@noemail.com' limit 1]; 88 | System.RunAs(cuser) { 89 | PageReference pageRef = Page.CommunityHome; 90 | Test.setCurrentPage(pageRef); 91 | onb_RegisterEntityDetailsController controller = new onb_RegisterEntityDetailsController(); 92 | controller.getParentAccounts(); 93 | } 94 | } 95 | 96 | @isTest 97 | static void testViewPageAsAdmin() { 98 | } 99 | } 100 | // Positive Tests 101 | // 1. set up data 102 | // 2. execute the logic we are testing 103 | // 3. query for updated record 104 | // 4. assert expected result 105 | // Negative Tests 106 | 107 | // Exception Tests (exceptions are thrown as expected) 108 | 109 | // Bulk Tests (everything still works when we are dealing with lots of records) 110 | 111 | /** 112 | Set up test for custom controller: 113 | 1. set the current page 114 | PageReference pageRef = Page.EmployeeBonuses; 115 | Test.setCurrentPage(pageRef); 116 | 117 | 2. set up the controller 118 | EmployeeBonusController ctrl = new EmployeeBonusController(); 119 | 120 | 3. call method(s) in the controller 121 | ctrl.doInit(); 122 | 123 | 4. check the resulting data by referencing the property in the class 124 | List employees = ctrl.employees; 125 | 126 | 5. assert expectations 127 | System.assertEquals(2, ctrl.employees.size(), 'The list should have two employees'); 128 | System.assertEquals(0, ApexPages.getMessages().size(), 'There should be no error messages on the page'); 129 | 130 | 131 | Set up the Lightning Component Controller: 132 | 1. set the current page 133 | PageReference pageRef = Page.EmployeeBonuses; 134 | Test.setCurrentPage(pageRef); 135 | 136 | 2. Call the @AuraEnabled method 137 | List employees = EmployeeBonusController.getEmployeeList(); 138 | 139 | // call method(s) in the controller 140 | ctrl.doInit(); 141 | 142 | // check the resulting data by referencing the property in the class 143 | List employees = ctrl.employees; 144 | 145 | // assert expectations 146 | System.assertEquals(2, ctrl.employees.size(), 'The list should have two employees'); 147 | System.assertEquals(0, ApexPages.getMessages().size(), 'There should be no error messages on the page'); 148 | */ -------------------------------------------------------------------------------- /VisibleSampleClass/Opportunity Contact Role/Opportunity1.tgr: -------------------------------------------------------------------------------- 1 | trigger Opportunity1 on Opportunity (after insert) { 2 | OpportunityContactRole.AfterInsertOpportunity( 3 | trigger.new, trigger.newMap 4 | ); 5 | } -------------------------------------------------------------------------------- /VisibleSampleClass/Opportunity Contact Role/OpportunityContactRole.cls: -------------------------------------------------------------------------------- 1 | // Enforce that every opportunity is created with an OpportunityContactRole 2 | // (has a contact associated with it) 3 | public class OpportunityContactRole { 4 | public static void AfterInsertOpportunity( 5 | List newList, 6 | Map newMap) { 7 | List ocrs = 8 | [SELECT ID, ContactID, isPrimary, OpportunityID 9 | FROM OpportunityContactRole 10 | WHERE OpportunityID in :newmap.keyset()]; 11 | 12 | Set OcrOpportunities = new Set(); 13 | 14 | for(OpporunityContactRole ocr: ocrs) 15 | OcrOpportunities.add(ocr.OpportunityID); 16 | 17 | for(Opportunity op: newList); { 18 | if(! OcrOpportunities.contains(op.id)) 19 | op.addError('Opportunity Contact Role is required to create an opportunity'); 20 | } 21 | 22 | //Other functionality 23 | } 24 | } -------------------------------------------------------------------------------- /VisibleSampleClass/VisibleSampleClass.cls: -------------------------------------------------------------------------------- 1 | public class VisibleSampleClass { 2 | // Private member variables 3 | @TestVisible private Integer recordNumber = 0; 4 | @TestVisible private String areaCode = '415'; 5 | // Public member variable 6 | public Integer maxRecords = 1000; 7 | 8 | // Private inner class 9 | @TestVisible class Employee { 10 | String fullName; 11 | String phone; 12 | 13 | // Constructor 14 | @TestVisible Employee(String s, String ph) { 15 | fullName = s; 16 | phone = ph; 17 | } 18 | } 19 | 20 | // Private method 21 | @TestVisible private String privateMethod(Employee e) { 22 | System.debug('I am private'); 23 | recordNumber++; 24 | String phone = areaCode + '' + e.phone; 25 | String s = e.fullName + '\'s phone number is ' + phone; 26 | System.debug(s); 27 | return s; 28 | } 29 | 30 | // Private method 31 | @TestVisible void publicMethod() { 32 | maxRecords++; 33 | System.debug('I am public'); 34 | } 35 | 36 | // Private custom exception class 37 | @TestVisible private class MyException extends Exception {} 38 | } --------------------------------------------------------------------------------