I have a custom object that is mirrored (Service_Order__c -> Opportunity) to when new records are created, the most part of the apex is bulkified however I am having trouble understanding how maps work and how get get the inserted ID's from Opportunity so I can update my Service_Order__c and my OpportunityContactRole objects.

Could someone explain how to get these ID's and how I update/insert the record in my trigger?

So I need to update Service_Order__c > OpportunityID__c and insert OpportunityContactRole > OpportunityID__c.

trigger MirrorOpportunity on Service_Order__c (before insert,after insert){

    Id UserId = UserInfo.getUserId();
    User user = [select AccountId, ContactId from User where id=:UserId];

    String stage = '01 - Pre-Bid';

    Stages__c s = [SELECT Id, Name, Value__c FROM Stages__c WHERE Name = :stage];
    User uO = [select id, usertype, userroleid from User where userroleid = '00ED0000001WmkV' AND IsActive=true LIMIT 1];

    list<Opportunity> oppList = new list<Opportunity>();
    list<Status_History__c> statusHistoryList = new list<Status_History__c>();
    list<OpportunityContactRole> oppContactList = new list<OpportunityContactRole>();

    for(Service_Order__c so : trigger.new) {

        if(trigger.isBefore) {

            Opportunity opp = new Opportunity();
            opp.StageName = stage;
            Date oppcloseddate = so.Project_Deadline__c;
            so.Account__c = user.AccountId;
            so.Contact__c = user.ContactId;
            opp.Name = so.Name;
            oppcloseddate = oppcloseddate.addDays(120);
            opp.CloseDate = oppcloseddate ;
            opp.LeadSource = so.Lead_Source__c;
            opp.AccountId = so.Account__c;
            so.Opp_Status__c = s.Value__c;    
            opp.Description = so.Description__c;                
            opp.Customer_Name__c = so.Customer_Name__c;

            opp.OwnerId = uO.id;

            so.Opportunity__c = opp.Id;


        if(trigger.isAfter) {
            Status_History__c sh = new Status_History__c();
            sh.name = s.Value__c;                
            sh.Service_Order__c =trigger.new[0].Id;

            OpportunityContactRole oppContact = new OpportunityContactRole();
            oppContact.ContactId = user.ContactId;
            oppContact.IsPrimary = true;
            oppContact.OpportunityId = '';

    } // end for loop

    insert oppList;
    insert statusHistoryList;
    insert oppContactList;

  • What does the following line Stages__c s = [SELECT Id, Name, Value__c FROM Stages__c WHERE Name = :stage]; do? I don't understand this since stage is a string constant. Also, are you able to combine any of your queries into single queries? This is a lot of queries to run with each execution of the trigger!
    – crmprogdev
    Feb 5, 2015 at 14:17
  • It fetches the Value__c from a Custom Setting and inserts into my Stage_History__c object. It is used inside the isAfter part of the trigger. Feb 5, 2015 at 14:19
  • Then at a minimum, the query should be located inside the isAfter code so that it is only used inside that portion of your code and not every time your trigger runs. Are you unable to use something like Stages__c s = Stages__c.getValues('01 - Pre-Bid'); to return your custom settings and save a query?
    – crmprogdev
    Feb 5, 2015 at 14:36
  • Will there be a difference in using this instead of SOQL? I need to somehow get a list of the ID's inserted and then match them to the Service_Order__c. From some of the research I've done myself I think Maps is the funtion I need to use but I'm not 100% sure how to use/implement them. Feb 5, 2015 at 14:47
  • Below I've shown you in my answer how to do the mapping in general with trigger.new to transfer the values to opportunity. If Opportunity__c is the OppId, then you check to see if that key value matches before performing the update. The issue will be how to do the bulkified user Accounts an Contacts along with Opp_Status. That part is unclear to me as I don't understand your relationships on the latter.
    – crmprogdev
    Feb 5, 2015 at 15:07

1 Answer 1


As for mapping, this can easily be mapped by doing something like the following:

Map<Id, list<Service_Order__c> mapSO = new Map<Id, list<Service_Order__c>();
mapSO = trigger.newMap;
set<Id> soIds = mapSO.keyset();

if(trigger.isBefore) {

   for(Id i:soIds){

      Opportunity opp = new Opportunity();
      opp.StageName = stage;
      Date oppcloseddate = mapSO.get(i).Project_Deadline__c;
      opp.Name = mapSo.get(i).Name;
      oppcloseddate = mapSO.get(i).closeddate.addDays(120);
      opp.CloseDate = oppcloseddate ;
      opp.LeadSource = mapSO.get(i).Lead_Source__c;
      opp.AccountId = mapSO.get(i).Account__c;
      opp.Description = mapSO.get(i).Description__c;                
      opp.Customer_Name__c = mapSO.get(i).Customer_Name__c;
      opp.Id = mapSO.get(i).Opportunity__c;
      opp.OwnerId = uO.id;



These lines will need fixed. You'll need to figure out how to match these up when this is bulkified.

//  so.Account__c = user.AccountId;
//  so.Contact__c = user.ContactId;
//  so.Opp_Status__c = s.Value__c;
  • Any ideas on how I can match those values up? Feb 10, 2015 at 10:48
  • 1
    If you can find one of the other values in the map that will be uniquely associated with those field values, you'll then be able to find the map key to add the other fields to the map using a statement within a for loop like the following: if(unique_field=mapSO.get(i).equiv_unique_field mapSO.put(i, so.Account__c)); Note that i is an Id iterator, but you could also use an implicit loop.
    – crmprogdev
    Feb 10, 2015 at 13:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .