6

NEW SOLUTION

trigger AutoCreateSubs on Contract_Overview__c (after insert, after update) {
 List<Subs_Serviced_On_Contract__c> subs = new List<Subs_Serviced_On_Contract__c>();

    //For each position processed by the trigger, add a new  

    //Subs_Serviced_On_Contract record for the specified Subsidiaries_On_Contract__c.  

    //Note that Trigger.New is a list of all the new positions  

    //that are being created.  

    for (Contract_Overview__c newContract : Trigger.New) {
        if (newContract.Subsidiaries_On_Contract__c != '[]') {
            // split out the multi-select picklist using a comma delimiter
            System.debug('Subsidiaries_On_Contract__c ' + newContract.Subsidiaries_On_Contract__c);

            String temp = newContract.Subsidiaries_On_Contract__c;
            temp = temp.replace(']','');
            temp = temp.replace('[','');
            String[] all = temp.split(',');

            for(String subsoncontract: all){
                subsoncontract = subsoncontract.normalizeSpace();
                //for(String subsoncontract: newContract.Subsidiaries_On_Contract__c.split(',')){
                SubsidiariesAndBrands__c sac = new SubsidiariesAndBrands__c(Name = subsoncontract);
                    Subs_Serviced_On_Contract__c ssoc = new Subs_Serviced_On_Contract__c(
                        Name = subsoncontract,
                        Contract_Overview__c = newContract.Id,
                        Account__c = newContract.Account__c,
                        Subsidiaries_and_Brands__c = subsoncontract,
                        Contract_and_Sub__c = newContract.Name + '~' + subsoncontract,
                        Contract_Start_Date__c = newContract.Contract_Start_Date__c,
                        Contract_End_Date__c = newContract.Contract_End_Date__c,
                        Logo_Usage_Allowed__c = 'Yes');

                ssoc.Subsidiaries_and_Brands__r = sac;

            subs.add(ssoc);
            }
        } 
    }

    upsert subs Contract_and_Sub__c;

}

This is how my code is set up now per your suggestions. I am getting this error from the trigger when saving :

Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, AutoCreateSubs: execution of AfterInsert caused by: System.StringException: Invalid id: Nescafe Trigger.AutoCreateSubs: line 26, column 1: []

In this case, Nescafe is the name of one of the subsidiaries chosen.

Line 26 is this one :

Subs_Serviced_On_Contract__c ssoc = new Subs_Serviced_On_Contract__c(

just so we both are on the same page :

SubsidiariesAndBrands__c = Subsidiary account object (should contain id in Name field)

Subs_Serviced_On_Contract__c = the child object

Subsidiaries_and_Brands_c = lookup field on the new child document referencing the subsidiary's account (SubsidiariesAndBrands_c)

Thanks so much for the help. I really appreciate it.

  • So when you do this, is there some kind of error message you receive? – Jeremy Nottingham Mar 24 '13 at 1:05
  • What is the output of the system.debug() call, just below the if? – rael_kid Mar 24 '13 at 8:13
  • @JeremyNottingham and Lex : I have included an update to my original post which has much more information and an error message. I'm sorry if it's confusing. It's somewhat of a complicated situation but I wanted to include all the information to help. Thank you very much for your help. I really appreciate it. – Zoom_v Mar 24 '13 at 15:56
5

Strings are converted to ids automatically, so you shouldn't need to do anything special. Here's an example from my dev org:

    public class IdTest {

    public static void testIdAsString()
    {
        String idsStr='0018000000pGTrn;0018000000tzbJr;0018000000tzbJw';
        List<Contact> conts=new List<Contact>();
        for (String idStr : idsStr.split(';'))
        {
            Contact cont=new Contact(FirstName='Unit', LastName='Test', AccountId=idStr);
            conts.add(cont);
        }

        insert conts;

        System.debug('### Contacts = ' + conts);
    }
}

note how the AccountId field is populated directly from the idStr string. The debug output for this is:

09:02:10.351 (351115000)|USER_DEBUG|[15]|DEBUG|### Contacts = (Contact:{AccountId=0018000000pGTrnAAG, FirstName=Unit, Id=0038000001NuTAlAAN, LastName=Test}, Contact:{AccountId=0018000000tzbJrAAI, FirstName=Unit, Id=0038000001NuTAmAAN, LastName=Test}, Contact:{AccountId=0018000000tzbJwAAI, FirstName=Unit, Id=0038000001NuTAnAAN, LastName=Test})

If you are seeing an error from your code, I would think its likely to be one of the following:

  1. The Subsidiaries_On_Contract__c field doesn't contain ids
  2. The Subsidiaries_On_Contract__c doesn't contain the right type of id (e.g. I have to use account ids for my contacts - which have to start with 001. If I used an opportunity id that would fail)
  3. You aren't parsing the Subsidiaries_On_Contract__c field correctly.

Looking at your code, I think #3 is the most likely if Subsidiaries_On_Contract__c is a multi-select picklist, as this will contain a semi-colon separated list of values. Comma separated and square bracket delimited usually means a list converted to a string to me (much like my debug statement above). If it isn't a multi-select picklist, I'd output some debug to show the value of each "id string" that you are iterating - as you have replaced the opening and closing square brackets with commas, it may be that you are getting empty values for the first and last elements when the string is split.

Based on your updates to your original post, you have the sub account names rather than ids, but you'll need to use the ids to populate the lookup field.

You should therefore retrieve all of the sub account ids based on the names, stores them in a map and use them when creating the records. Something like the following (which assumes that your sub accounts are still modelled as accounts) - its not great, as there's some repetition, but hopefully you get the picture:

trigger AutoCreateSubs on Contract_Overview__c (after insert, after update) 
{
   List<Subs_Serviced_On_Contract__c> subs = new List<Subs_Serviced_On_Contract__c>();

   // get the full list of sub account names for all records being processed by the trigger

   List<String> subAccNames=new List<String>();

   for (Contract_Overview__c newCont : Trigger.New) 
   {
      if (newCont.Subsidiaries_On_Contract__c != '[]') 
      {
         // split out the multi-select picklist using a comma delimiter
         System.debug('Subsidiaries_On_Contract__c ' + newCont.Subsidiaries_On_Contract__c);

         String temp = newCont.Subsidiaries_On_Contract__c;
         temp = temp.replace(']','');
         temp = temp.replace('[','');
         String[] all = temp.split(',');
         subAccNames.addAll(all);
      }
   }

   // get the ids for all sub accounts and store in a map keyed by name
   Map<String, Id> subAccIdsByName=new Map<String, Id>();
   for (SubsidiariesAndBrands__c subAcc : [select id, Name from SubsidiariesAndBrands__c where Name in :subAccNames) 
   {
      subAccIdsByName.put(subAcc.Name, subAcc.id);
   }

   //For each position processed by the trigger, add a new  

   //Subs_Serviced_On_Contract record for the specified Subsidiaries_On_Contract__c.  

   //Note that Trigger.New is a list of all the new positions  

   //that are being created.  

   for (Contract_Overview__c newContract : Trigger.New) 
   {
      if (newContract.Subsidiaries_On_Contract__c != '[]') 
      {
         // split out the multi-select picklist using a comma delimiter
         System.debug('Subsidiaries_On_Contract__c ' + newContract.Subsidiaries_On_Contract__c);

         String temp = newContract.Subsidiaries_On_Contract__c;
         temp = temp.replace(']','');
         temp = temp.replace('[','');
         String[] all = temp.split(',');

         for(String subsoncontract: all)
         {
            subsoncontract = subsoncontract.normalizeSpace();
            //for(String subsoncontract: newContract.Subsidiaries_On_Contract__c.split(',')){
            SubsidiariesAndBrands__c sac = new SubsidiariesAndBrands__c(Name = subsoncontract);
            Subs_Serviced_On_Contract__c ssoc = new Subs_Serviced_On_Contract__c(
                    Name = subsoncontract,
                    Contract_Overview__c = newContract.Id,
                    Account__c = newContract.Account__c,
                    Subsidiaries_and_Brands__c = subAccIdsByName.get(subsoncontract),  // GET THE SUB ACCOUNT ID BASED ON NAME
                    Contract_and_Sub__c = newContract.Name + '~' + subsoncontract,
                    Contract_Start_Date__c = newContract.Contract_Start_Date__c,
                    Contract_End_Date__c = newContract.Contract_End_Date__c,
                    Logo_Usage_Allowed__c = 'Yes');

            subs.add(ssoc);
         }
      } 
   }

   upsert subs;
}
| improve this answer | |
  • Bob - thank you very much for your help. I have included an update in my original post which contains much more information to answer your questions. I hope it's not too confusing. It's a really long-winded explanation. – Zoom_v Mar 24 '13 at 15:54
  • I've updated the answer based on what you have added to the question. It boils down to: retrieve all sub accounts records in the trigger based on their name, create a map of sub account ids keyed by name and when creating the Subs_Serviced_On_Contract__c record, retrieve the id for the SubAccount__c field based on the sub account name. – Bob Buzzard Mar 24 '13 at 19:41
  • Bob - thank you very much for the help. That's really great. However, I have tried to use the code you gave here but I'm getting a "Duplicate variable: newContract" error. I also would get a "Variable does not exist: subs" error for the upsert line at the end of the code (not included in your example). Do you have any ideas on this ? Thanks again for your help. – Zoom_v Mar 25 '13 at 1:20
  • I've tweaked the code so the first loop is now controlled by a variable called 'newCont' - make sure to change all references inside that loop. WRT to the "upsert subs Contract_and_Sub__c;" statement - I don't think you need the 'Contact_and_Sub__c' part - what is that intended to do? Also, you should put this outside the iteration of trigger.new, otherwise if you have 200 records being processed in the trigger, you will break governor limits. – Bob Buzzard Mar 25 '13 at 8:46
  • Thank you so much on that. I have updated my original post again in order to show you how the trigger is currently coded after I applied some minor changes to adapt it to my code. The latest code appears under the Second Update label. Btw : The Contract_and_Sub field is funtioning as an external id for the newly created child record. This is in there to prevent multiple new child records to be created for a subsidiary when the parent is modified and saved. Thank you very much for your help on this. – Zoom_v Mar 25 '13 at 13:46
0

Zoom, you can do this if you have an external-id on the sub-account object. You can keep the external-id same as the Name.

Then you'll need to point the relationship from your child object to Subaccount as below:

    Sub_Account_c sac = new Sub_Account_c(external_id__c = subsoncontract);
    Subs_Serviced_On_Contract__c ssoc = new Subs_Serviced_On_Contract__c(
                                       Name = subsoncontract,
                                       Contract_Overview__c = newContract.Id,
                                       Account__c = newContract.Account__c,
                                       SubAccount__c = subsoncontract,
                                       Contract_and_Sub__c = newContract.Name + '~' + subsoncontract,
                                       Contract_Start_Date__c = newContract.Contract_Start_Date__c,
                                       Contract_End_Date__c = newContract.Contract_End_Date__c,
                                       Logo_Usage_Allowed__c = 'Yes');
    ssoc.Sub_Account_r = sac; //Notice the __r here.
subs.add(ssoc);
| improve this answer | |
  • I didn't even notice your suggestions until just now. I attempted to apply them but I got an error when the trigger kicked off. I have edited my original post and put NEW SOLUTION at the top. That is how my code looks right now. I included the error as well. I'm not exactly sure what's happening. Thank you so much for your help in this Ashish. – Zoom_v Mar 26 '13 at 20:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.