triggerssalesforceapextest-class

How to create an Apex Class?


Through plenty of trial and error, I've created the functioning trigger in my sandbox. My issue is that I would like to now apply it to my live org but I can't seem to understand the whole apex class thing.

How can I create a class?

The idea behind my trigger is that when an opportunity record is saved, the soql query will look at the picklist value selected in the category field and find an an active vendor or member service account type with a matching name and bring over its salesforce id. Dropping that sfid into my Vendor Name lookup field will allow me to have the relationship between the opportunity and vendor/member service account that I need for other workflow rules and field updates.

    trigger Find_Vendor on Opportunity (before insert)
    {
       for(Opportunity u:trigger.new)
       {
          if(u.Vendor_Name__c == null)
          {
              u.Vendor_Name__c =   [Select Id From Account
                             Where (Account_Type__c = 'Vendor'
                             OR Account_Type__c = 'Member Services')
                             AND Status__c = 'Active'
                             AND Name = :u.Category__c limit 1].Id;
          }
       }
    }

Solution

  • I would not deploy this trigger to production it has many issues and would likely break because you are doing a SOQL query in a for loop also the logic seems not well thought out. Seeing that it seems you are not very versed in writing triggers you should probably look at a declarative solution such as the process builder and a headless flow where you can achieve the same result. If you insist on using triggers I would recommend using something like the following:

     trigger Find_Vendor on Opportunity (before insert)
    {
       Set<String> categories = new Set<String>();
       Map<String, Id> categoryAccountIdMap = new Map<String, Id>();
       for(Opportunity u:trigger.new)
       {
          if(u.Category__c != null)
          {
               categories.add(u.Category__c);
          }
       }
       List<Account> categoryAccounts = [Select Id From Account
                             Where (Account_Type__c = 'Vendor'
                             OR Account_Type__c = 'Member Services')
                             AND Status__c = 'Active'
                             AND Name IN :categories];
       for(Account acct : categoryAccounts){
           if(!categoryAccountIdMap.containsKey(acct.Name)){
                categoryAccountIdMap.put(acct.name, acct.Id);
           }
       }
       for(Opportunity u:trigger.new)
       {
          if(u.Vendor_Name__c == null && categoryAccountIdMap.containsKey(u.Category__c))
          {
              u.Vendor_Name__c =   categoryAccountIdMap.get(u.Category__c);
          }
       }
    }
    

    You would also need some test coverage of your trigger to be able to release, but just inserting an opportunity in the test should suffice

    @IsTest
    private class SomeTestClassName {
    
    @isTest
    static void testOppVendor() {
     //you may need to add required fields to these objects to actually insert  them
        Account a = new Account(Name = 'Category 1');
        insert  a;
        Opportunity o = new Opportunity(Name = 'test', StageName = 'Closed Won', Category__c = 'Category 1');
        insert o;
        o = [SELECT Vendor_Name__c FROM Opportunity where Id = :o.Id];
        System.assertEquals(a.Id, o.Vendor_Name__c);
    }
    

    That being said there are a number of best practices not being used here such as a test data factory and moving business logic from triggers into domain classes that you should definitely look into getting familiar with.