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
Sonia GenesseSonia Genesse 

Auto update a lookup field with a Trigger on a Customer Object

Hi All, 

I have a Custome Object called Service_Record_History__c that requires a Trigger to update a Lookup field named Installed_Product__c.

This is the first trigger I am attempting to write, so please bare with me! :)

Below is the Trigger I have written, and I'm receiving this error:   Error: Compile Error: Illegal assignment from List<SVMXC__Installed_Product__c> to Id at line 6 column 13

Also, in my Select statement I'm concerned that it is selecting ALL SVMXC__Installed_Product__c ID's rather than the specific related ID that is needed.
 

trigger InstallProductID_Trgr  on Service_Record_History__c ( before insert, before update ) {

for (Service_Record_History__c  c  :Trigger.new) {
        if(c.Installed_Product__c <> null)

            c.Installed_Product__c =  [SELECT Name FROM SVMXC__Installed_Product__c];

      }
}
Best Answer chosen by Sonia Genesse
pconpcon
Yep that helps out a ton.  This is actually a pretty simple trigger
 
trigger PopulateProduct on Service_Record_History__c (before insert) {
    Set<String> serialNumbers = new Set<String>();
    Map<String, SVMXC__Installed_Product__c> serialToProductMap = new Map<String, SVMXC__Installed_Product__c>();

    for (Service_Record_History__c srh : Trigger.new) {
        serialNumbers.add(srh.Serial_Number__c);
    }

    serialNumbers.remove(null);

    if (!serialNumbers.isEmpty()) {
        for (SVMXC__Installed_Product__c product : [
            select Name
            from SVMXC__Installed_Product__c
            where Name in :serialNumbers
        ]) {
            serialToProductMap.put(product.Name, product);
        }   

        for (Service_Record_History__c srh : Trigger.new) {
            if (serialToProductMap.containsKey(srh.Serial_Number__c)) {
                srh.Installed_Product__c = serialToProductMap.get(srh.Serial_Number__c).Id;
            }
        }
    }
}

This trigger iterates over all of the new service record history objects, and adds their serial numbers to a set.  Then we query for all the products whose name matches that serial number.  Then we build a map of serial numbers to products.  Then we iterate over all the new service records again and if we find a product that matches then we set the lookup.

All Answers

pconpcon
There are a couple of things wrong with your trigger but we can deal with those it a little bit.  I'm confused as to what you are doing.  You are saying that if Installed_Product__c is not null then you want to select something from the SVMXC__Installed_Product__c object.  However like you said that is getting them all and you only want one product.  I'm assuming that the Installed_Product__c is a lookup or master-detail relation to the SVMXC__Installed_Product__c object.  So I don't know why you are trying to populate it.  If this isn't the case, can you tell me how you would expect filter out the SVMXC__Installed_Product__c objects?  Is there another field on Service_Record_History__c that determines what product should be assigned?
Pranav ChitransPranav Chitrans
Hello Sonia Genesse,

I have created one scenario related to your query.. It not exactly what u are trying to do.. but its logic is relatedd to your query... I have auto populated the website filed on account if it is null at the time of insertion... and the second logic is on SLA with different values for gold ,silver etc..
*****APEX TRIGGER****
trigger Accounttrigger2 on Account (before insert, before update)
{
 acc ahelper=new acc();
 if(trigger.isinsert&&trigger.isbefore)
 {
  ahelper.onbeforeinsert(trigger.new);
 }
}

***APEX CLASS***
public class acc
{
 public void onbeforeinsert(list<Account> triggernew)
 {
  POPULATEweb(triggernew);
  assignSLA(triggernew);
 }
 void POPULATEweb(list<Account> triggernew)
 {
  for(Account a:triggernew)
  {
   if(a.Website==null)
   a.Website='google.com';
  }
 }
 void assignSLA(list<Account> triggernew)
 {
  for(Account a:triggernew)
  {
   if(a.SLA__c=='Gold')
   {
    a.SLASerialNumber__c='10';
   }
    if(a.SLA__c=='Silver')
    a.SLASerialNumber__c='20';
   }
  } 
 }

I hope this will help you a little bit... If you are having still doubt you can go ahead with your new queries... :)
Sonia GenesseSonia Genesse
Hi Pcon

Yes the Installed_Product__c is a lookup relationship and the Service_Record_History__c has a field named Serial_Number__c, it corresponds to the SVMXC__Installed_Product__c object with the field name as Installed_Product_ID. I'm tring to have this field update automattically and not have the end user have to populate this field. So if the Installed_Product_ID (lookup) isn't populated on the 
Service_Record_History__c object record, the Related List on the SVMXC__Installed_Product__c object has no data.

The data that is in the Service_Record_History__c object is data that is loaded from a legacy system. I need to see it in a RL on the Installed Product.

Does this help clarify the question?

User-added image

 
pconpcon
Yep that helps out a ton.  This is actually a pretty simple trigger
 
trigger PopulateProduct on Service_Record_History__c (before insert) {
    Set<String> serialNumbers = new Set<String>();
    Map<String, SVMXC__Installed_Product__c> serialToProductMap = new Map<String, SVMXC__Installed_Product__c>();

    for (Service_Record_History__c srh : Trigger.new) {
        serialNumbers.add(srh.Serial_Number__c);
    }

    serialNumbers.remove(null);

    if (!serialNumbers.isEmpty()) {
        for (SVMXC__Installed_Product__c product : [
            select Name
            from SVMXC__Installed_Product__c
            where Name in :serialNumbers
        ]) {
            serialToProductMap.put(product.Name, product);
        }   

        for (Service_Record_History__c srh : Trigger.new) {
            if (serialToProductMap.containsKey(srh.Serial_Number__c)) {
                srh.Installed_Product__c = serialToProductMap.get(srh.Serial_Number__c).Id;
            }
        }
    }
}

This trigger iterates over all of the new service record history objects, and adds their serial numbers to a set.  Then we query for all the products whose name matches that serial number.  Then we build a map of serial numbers to products.  Then we iterate over all the new service records again and if we find a product that matches then we set the lookup.
This was selected as the best answer
Sonia GenesseSonia Genesse
Thanks! I'll give this a shot and see how it works out. I'll send another post either way.

~Sonia~
Sonia GenesseSonia Genesse
Hi Pcon

Looks like the Trigger is working perfectly when I create or clone a record. In the case of the 
Service_Record_History__c object these will only be imported (using Data Loader) for historical purposes, and no new records will ever be created.

How then does this Trigger work to support these loaded records? 

 
pconpcon
The data loader can still cause triggers to fire.  This trigger is bulk ready and should handle (with the exception of a really high 10k+ import) large data imports. 

However, if you are really worried about it, you could update whatever datasource you are importing and set the Installed_Product__c field to be the id of the correct SVMXC__Installed_Product__c prior to data loading and then you would not need the trigger.
Sonia GenesseSonia Genesse
Hi Pcon If the Trigger will fire on import, I’m totally fine with that solution. Thanks so much for your assistance and quick replies, it’s truly appreciated!!! ☺ I have a couple of other Triggers that I need as well, that will be similar in nature. I’ll try to modify this one to create the others, hopefully all goes well. ~Sonia~
pconpcon
If you don't mind creating a new post for those triggers and link to this one to add some more context.  It's better to try to keep each post to a single issue.
Sonia GenesseSonia Genesse
Created, but not sure how to link them??
 
pconpcon
There's no way to really "link" them, just mention the previous post in the body next time :)