function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
GRStevenBrookesGRStevenBrookes 

Apex Insert Trigger - Record Type

Hi World,

 

I am sure you will laugh at this  - probably so easy but..... I have  the following trigger - which will insert a case:

 

trigger AutoCreateAccountsCaseSI on Service_Agreement__c (after insert) 
{

if(!StaticClass.flag)
    {
        List<Case> listC = new List<Case>();
        
        for(Service_Agreement__c s : trigger.new)
        if(Trigger.isInsert)
            {
                if(s.HasAccountManager__c = 'Yes' )
                {
                  listC.add(new Case(
                  RecordType='01220000000MEEW',
                  Requested_By1__c=s.OwnerId,
                  Account=s.Related_Account__c,
                  Service_Agreement__c=s.Id,
                  Origin='Salesforce Process',
                  Type='New Account / Service Agreement',
                  Subject='Account Financial Approval',
                  Description='Please confirm reciept of required financial information and approval for service implementation'));
               }
            }
    
        if(listC.size() > 0)
        {
            insert listC;
        }
        StaticClass.flag = true ;
    }
}

 

 However, for some reason i am getting error on the:

 

RecordType='01220000000MEEW',

I have tried with and without quotes, but with quotes I am getting an error of:

 

'Save error: Invalid initial expression type for field RecordType, expecting: SOBJECT:RecordType (or single row query result of that type)'

 

Can any one help??

 

Thanks in advance.

 

 

Steve

 

 

Best Answer chosen by Admin (Salesforce Developers) 
bob_buzzardbob_buzzard

In this case you want to use  Service_Agreement__c=s.Id,  as the lookup field on the case object holds the id of the related object, not the object itself.

 

You'd only use the __r (or Account/RecordType) if you wanted to access fields from the related object, i.e. to traverse the relationship to the actual object.

All Answers

goabhigogoabhigo

I did not laugh, believe me.

 

Use this in your trigger:

Id rtId = [select Id,name from RecordType where name='Label of the record type' and SObjectType='Case' limit 1].Id;

 

Replace like this:

for(Service_Agreement__c s : trigger.new)
        if(Trigger.isInsert)
            {
                if(s.HasAccountManager__c = 'Yes' )
                {
                  listC.add(new Case(
                  RecordTypeId = rtId,

 

Let me know if still encounter any problem.

bob_buzzardbob_buzzard

RecordType is the relationship to the object itself.  You probably want the RecordTypeId field.  E.g.

 

listC.add(new Case(
           RecordTypeId='01220000000MEEW',

I'm also duty bound to say that its not usually a good idea to hardcode ids in triggers.

bob_buzzardbob_buzzard

Beaten to the punch by Abhi, who also gave a solution for the hardcoded record type!

 

Nice work.

GRStevenBrookesGRStevenBrookes

Thanks for the reply so I have done as you have said:

 

trigger AutoCreateAccountsCaseSI on Service_Agreement__c (after insert) 
{

if(!StaticClass.flag)
    {
        List<Case> listC = new List<Case>();
        Id rtId = [select Id,name from RecordType where name='Accounts' and SObjectType='Case' limit 1].Id;
        
        for(Service_Agreement__c s : trigger.new)
        if(Trigger.isInsert)
            {
                if(s.HasAccountManager__c = 'Yes' )
                {
                  listC.add(new Case(
                  RecordTypeId = rtId,
                  Requested_By1__c=s.OwnerId,
                  Account=s.Related_Account__c,
                  Service_Agreement__c=s.Id,
                  Origin='Salesforce Process',
                  Type='New Account / Service Agreement',
                  Subject='Account Financial Approval',
                  Description='Please confirm reciept of required financial information and approval for service implementation'));
               }
            }
    
        if(listC.size() > 0)
        {
            insert listC;
        }
        StaticClass.flag = true ;
    }
}

 

 

and am now getting:

 

 

Save error: Invalid initial expression type for field Account, expecting: SOBJECT:Account (or single row query result of that type)

bob_buzzardbob_buzzard

Same concept, but different line:

 

Account=s.Related_Account__c

 needs to be:

AccountId=s.Related_Account__c

 

GRStevenBrookesGRStevenBrookes

brill - so what would i put for Service_Agreement__c would it be Service_AgreementId__c or Service_Agreement__c.id

bob_buzzardbob_buzzard

If that is a custom lookup field, it will be Service_Agreement__c that contains the id, and if you wanted to refer to the related object instance it would be Service_Agreement__r.

GRStevenBrookesGRStevenBrookes

So I have put:

 

trigger AutoCreateAccountsCaseSI on Service_Agreement__c (after insert) 
{

if(!StaticClass.flag)
    {
        List<Case> listC = new List<Case>();
        Id rtId = [select Id,name from RecordType where name='Accounts' and SObjectType='Case' limit 1].Id;
        
        for(Service_Agreement__c s : trigger.new)
        if(Trigger.isInsert)
            {
                if(s.Has_Account_Manager__c = TRUE)
                {
                  listC.add(new Case(
                  RecordTypeId = rtId,
                  Requested_By1__c=s.OwnerId,
                  AccountId=s.Related_Account__c,
                  Service_Agreement__r=s.Id,
                  Origin='Salesforce Process',
                  Type='New Account / Service Agreement',
                  Subject='Account Financial Approval',
                  Description='Please confirm reciept of required financial information and approval for service implementation'));
               }
            }
    
        if(listC.size() > 0)
        {
            insert listC;
        }
        StaticClass.flag = true ;
    }
}

 

and am getting:

 

Save error: Invalid initial expression type for field Service_Agreement_r, expecting: SOBJECT:Service_Agreement __c (or single row query result of that type)

 

argghhhh - this is driving me nuts now!!

bob_buzzardbob_buzzard

In this case you want to use  Service_Agreement__c=s.Id,  as the lookup field on the case object holds the id of the related object, not the object itself.

 

You'd only use the __r (or Account/RecordType) if you wanted to access fields from the related object, i.e. to traverse the relationship to the actual object.

This was selected as the best answer
goabhigogoabhigo

Nobody can beat you Bob, you are the champ. Look at the way you explain. Great. Always a fan.

GRStevenBrookesGRStevenBrookes

thanks bob! You really are a star! Thank you.

 

The only problem i am having with this trigger now seems to be related to the test class - I am using:

 

@isTest
private class testopptrigger
{
private static testMethod void testopptriggerMethod(){
StaticClass.flag = false;
opportunity o = new opportunity();
o.StageName = 'Test Closed Won';
o.Name='Tester';
o.AccountId='0012000000ggi1T';
o.closedate=system.today();
o.secondary_lead_source__C='SB Database';
o.Primary_Opportunity_Contact__c='0032000000oBKsq';
insert o;
StaticClass.flag = false;
o.StageName = 'Test Closed Lost';
update o;
StaticClass.flag = false;
o.StageName = 'Test Closed Won';
update o;
}
}

 which used to work fine for me - however - since adding this new trigger - im getting an error on the test class saying:

 

DescriptionResourcePathLocationTypeSystem.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, AutoCreateSA: execution of AfterInsert
caused by: System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, AutoCreateAccountsCaseSI: execution of AfterInsert
caused by: System.FinalException: Record is read-only
Trigger.AutoCreateAccountsCaseSI: line 12, column 20: []
Trigger.AutoCreateSA: line 39, column 13: []testopptrigger.cls/GR Production Salesforce/src/classesline 13Force.com run test failure

 

any ideas?

bob_buzzardbob_buzzard

This usually means that you are attempting to update a field in one of the records from trigger.old/new - as its an after insert, the record is read only by that time.

 

However, looking at your code I can't see any attempt to do that.  One thing though, line 12 looks like a brace in the code that you last posted - is this the latest code, or is there more to it now?

GRStevenBrookesGRStevenBrookes

I have removed the AutoCreateAccountsCaseSI trigger now as it was preventing other triggers from 'triggering'!

 

Effectivly, this is what i have:

 

  1. Opportunity stage changed to 'Test Closed Won' - a new 'Service Agreement' is created.
trigger AutoCreateSA on Opportunity (after insert , before update)
{
    if(!StaticClass.flag)
    {
        List<Service_Agreement__c> listSA = new List<Service_Agreement__c>();
        
        for(Opportunity o : trigger.new)
        {
            if(Trigger.isUpdate)
            {
                if(o.StageName == 'Test Closed Won' && o.StageName != trigger.oldMap.get(o.Id).StageName)
                {
                  listSA.add(new Service_Agreement__c(
                  name = o.Name + ' - ' + o.Service_Type2__c,
                  Related_Account__c = o.accountid,
                  Related_Opportunity__c = o.id,
                  BD_Owner__c=o.OwnerId,
                  Primary_Contact__c = o.Primary_Opportunity_Contact__c
                  ));
                }
            }
            if(Trigger.isInsert)
            {
                if(o.StageName == 'Test Closed Won')
                {
                  listSA.add(new Service_Agreement__c(
                  name = o.Name + ' - ' + o.Service_Type2__c,
                  Related_Account__c = o.accountid,
                  Related_Opportunity__c = o.id,
                  BD_Owner__c=o.OwnerId,
                  Primary_Contact__c = o.Primary_Opportunity_Contact__c
                  ));
                }
            }
        }
    
        if(listSA.size() > 0)
        {
            insert listSA;
        }
        StaticClass.flag = true ;
    }
}

 2. Once this is created - a Service Implementation Record is created:

trigger AutoCreateSI on Service_Agreement__c (after insert)
{
    if(!StaticClass.flag)
    {
        List<Service_Implementation__c> listSA = new List<Service_Implementation__c>();
        
        for(Service_Agreement__c s : trigger.new)
        if(Trigger.isInsert)
            {
                if(s.Name != '' )
                {
                  listSA.add(new Service_Implementation__c(name = s.Name, Service_Agreements__c = s.id));
               }
            }
    
        if(listSA.size() > 0)
        {
            insert listSA;
        }
        StaticClass.flag = true ;
    }
    }

 I feel that this is perhaps the problem - as when Step 1 is triggered - i.e a Service Agreement is created - this is when I want the Case to also be created - however I gather that the record is read only as it is creating the the Service Implementation Record. This is what i have so far for this Case trigger:

 

trigger AutoCreateAccountsCaseSI on Service_Agreement__c (after insert)
{
    if(!StaticClass.flag)
    {
        List<Case> listC = new List<Case>();
        Id rtId = [select Id,name from RecordType where name='Accounts' and SObjectType='Case' limit 1].Id;
        
        for(Service_Agreement__c s : trigger.new)
        {
            if(Trigger.isUpdate)
            {
                if(s.Has_Account_Manager__c = TRUE)
                {
                  listC.add(new Case(
                  RecordTypeId = rtId,
                  OwnerId='00520000001S0lx',
                  Requested_By1__c=s.OwnerId,
                  AccountId=s.Related_Account__c,
                  Service_Agreement__c=s.Id,
                  Origin='Salesforce Process',
                  Type='New Account / Service Agreement',
                  Subject='Account Financial Approval',
                  Description='Please confirm reciept of required financial information and approval for service implementation'
                  ));
                }
            }
            if(Trigger.isInsert)
            {
                if(s.Has_Account_Manager__c = TRUE)
                {
                  listC.add(new Case(
                  RecordTypeId = rtId,
                  OwnerId='00520000001S0lx',
                  Requested_By1__c=s.OwnerId,
                  AccountId=s.Related_Account__c,
                  Service_Agreement__c=s.Id,
                  Origin='Salesforce Process',
                  Type='New Account / Service Agreement',
                  Subject='Account Financial Approval',
                  Description='Please confirm reciept of required financial information and approval for service implementation'
                  ));
                }
            }
    
        if(listC.size() < 1)
        {
            insert listC;
        }
        StaticClass.flag = true ;
    }
}
} 

So, i guess my question is - how do you get two triggers to fire after the service agreement is created?

 

Again, thanks in advance for your help.

bob_buzzardbob_buzzard

This may be simpler than it appears - the line in question is the following:

 

            if(s.Has_Account_Manager__c = TRUE)

 

Which is assigning the value true, rather than comparing.  You'll need the '==' operator for comparison.  

GRStevenBrookesGRStevenBrookes

ok - so i have made that change and deployed - however now when creating a new service agreement i get no Service Implementation or Case! - Your the expert - clearly, but is this failing becuase effectivly i am trying to trigger two actions on the same record at once? Is their a way to merge the triggers into one? Would that have any effect?

GRStevenBrookesGRStevenBrookes

Your right though.....

 

System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, AutoCreateSA: execution of AfterInsert
caused by: System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, AutoCreateAccountsCaseSA: execution of AfterInsert
caused by: System.FinalException: Record is read-only
Trigger.AutoCreateAccountsCaseSA: line 29, column 20: []
Trigger.AutoCreateSA: line 39, column 13: []

 

Looks like when the AutocreateSA is inserting the record AutoCreateAccountsCaseSA is not able to check to see if(s.Has_Account_Manager__c == TRUE) and then reporting back as Read-Only.

 

Arghhhh!!!!

bob_buzzardbob_buzzard

You should be able to have more than one trigger for the same action - the only thing you can't do is control the order it which they take place.

 

I don't see why this would change the service implementation situation - those get created when the opportunity stage transitions (or is inserted) as "Test Closed Won" and that hasn't changed.

 

No case would indicate that the Has_Account_Manager__c field of the Service_Agreement__c object has the value 'false' - how is this value set - I can't see it in the objects that are inserted by the trigger - is it a formula field or similar?

bob_buzzardbob_buzzard

The line in the latest exception is also using the single = character (at least in the code posted above) which will again try to assign the value rather than compare with that value.

GRStevenBrookesGRStevenBrookes

I have changed that now - still through up error. the as_Account_Manager__c field of the Service_Agreement__c object is updated by a workflow that checks the box to TRUE when: 

OR 
(OwnerId="00520000001Ry6n", 
OwnerId="00520000001RzHc", 
OwnerId="00520000001Ry7W", 
OwnerId="00520000001y0qw" 
)
bob_buzzardbob_buzzard

That may be the problem - according to the order of execution in the Apex Developer's Guide, workflow doesn't happen until the after triggers have completed.  

GRStevenBrookesGRStevenBrookes

just to go back at bit - when the service agreement is created a workflow sets who the record owner is based on a value from within the opportunity - basically either:

 

OwnerId="00520000001y0qw"

OwnerId="00520000001Ry6n"

OwnerId="00520000001RzHc"

OwnerId="00520000001Ry7W"

 

or 'Manual Allocation Required'

 

Now....if its 'Manual Allocation Required' then the 'Has_Account_Manager__c field of the Service_Agreement__c' will be set to FALSE - if it is any of the above - then it will be set to TRUE. Or If the user changes the owner from MAR to one of the above, at that stage the Has_Account_Manager__c field of the Service_Agreement__c will be set to TRUE.

bob_buzzardbob_buzzard

Understood.  However, by the time the after insert trigger fires and checks the Has_Account_Manager__c field, I don't think the workflow will have fired.  Thus the if condition evaluates to false in all cases and no case gets created.

GRStevenBrookesGRStevenBrookes

So, i have changed the 

if(s.Name != '')

 on the ...CreateCase Trigger to see if this helps - and now - again, i dont get a case or an implementation record.

 

In your wealth of experience is there any advice you could give on how to achieve what I am looking for which is effectivly for a case and service implementation recrod to be created. or is there any de-bugging I can do?

bob_buzzardbob_buzzard

So do you get the Service_Agreement__c record?

 

I'm wondering if you have a race condition due to the StaticClass.flag - once one of the triggers completes this will be set to true and later ones will bypass.

 

If it were me, I'd turn on debug logging for my user and add some debug statements.  Initially, I'd add some just to check that it is making it into each of my triggers as I expect, state of the StaticClass.flag property etc.

GRStevenBrookesGRStevenBrookes

Ok - I have run a finest log from the point Opportunity is marked to 'Test Closed Won' onwards - it means nothing to me - not sure if it will help though:

 

Log Link

GRStevenBrookesGRStevenBrookes

Yes - always get the ServiceAgreement__c record and if i delete the ....AutoCreateAccountsCaseSA.trigger then I get the service implementation record also. 

bob_buzzardbob_buzzard

The log shows that the case is created.  However, it doesn't get inserted.  Looking back on the code, this line of the case trigger:

 

  if(listC.size() < 1)
        {
            insert listC;
        }

 will only insert a case if the list has a size of zero, presumably this should be >0?

GRStevenBrookesGRStevenBrookes
Mmm I thought that too and have changed it but makes no difference and in any event at the time the case is created their wouldnt be any other cases their so shouldnt be a problem.
bob_buzzardbob_buzzard

That line of code would cause a problem, as the condition would only be true if the list contained zero elements - i.e. it was empty.  As soon as you added your case, the size would be ==1 so it would have skipped the insert.

 

Have you got a revised log now that you've changed that part of the trigger?

santhossanthos

Hi Abhi,

 

I have this recordtype issue.

 

My trigger code goes like this:

 

trigger AlerttypeID on Lead (before insert) {
    string rtid1='012800000007dzq';
    string rtid2='01280000000Lqh8';
    //id rtId1 = [select id, name from RecordType where name='Jumbo Paid Search' and SObjectType='lead' limit 1].Id;
    //id rtId2 = [select id, name from RecordType where name=' CMI.com ACQ' and SObjectType='lead'limit 1].Id;
    for(lead le: Trigger.new){
        if(le.RecordTypeid==rtid1)
            le.AlertTypeID__c='DTC_ACQ1_A';
            
        else if(le.RecordTypeid==rtid2)
            le.AlertTypeID__c='DTC_ACQ1_A';
            
        else
            le.AlertTypeID__c='';
            
    }
}

 

This code works fine in the sandbox but its not working in the production. The AlertTypeID__c field is not auto populating in the production.

 

Then I tried your code, you can find that in my code( commented out). But I am getting the below error.

 

Error:  execution of BeforeInsert caused by: System.QueryException: List has no rows for assignment to SObject

calvin_nrcalvin_nr

Brilliant. This helped me.

Neeta Jain 7Neeta Jain 7

Dear Experts, please help me. I have to Update current below trigger to allow the new case record type (compliance) with origin as Manual. suggestions pls?

 

trigger CaseTrigger on Case (before insert, after insert, after update) {

    Set<Id> phoneCases = new Set<Id>();

    Id supportRecTypeId = Schema.SObjectType.Case.getRecordTypeInfosByName().get('Support,Compliance').getRecordTypeId();

    if (Trigger.isBefore && Trigger.isInsert) {
        StopTrigger.stopTriggerRun();
    }

    if (Trigger.isAfter && Trigger.isUpdate) {

        system.debug('StopTrigger.canIRun() : '+StopTrigger.canIRun());

        if (StopTrigger.canIRun()) {

            for (Case cse : Trigger.new) {

                Case cse_old = Trigger.oldMap.get(cse.Id);

                if (cse.RecordTypeId == supportRecTypeId && cse.Origin == 'Phone' && cse.s_Phone_Email_Verification__c != null && cse_old.s_Phone_Email_Verification__c != cse.s_Phone_Email_Verification__c) {
                    phoneCases.add(cse.Id);
                    
                    
                }
            }

            if (phoneCases.size() > 0) {
                CaseTriggerHandlerWithoutSharing.phoneCaseProcess(phoneCases);
            }
        }
    }

    if (Trigger.isAfter && Trigger.isInsert) {
        CaseTriggerHandler.callIntegration(Trigger.new);
    }
}