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
JakesterJakester 

Trigger to update AccountId of related object

We have this nifty custom object which tracks our customer's hardware specs called Hardware_Information__c. It's a child of Account. Sometimes we provide that hardware to them, and sometimes they provide their own. When we provide it to them, we link the Asset entry to the hardware_information__c via the Associated_Product__c lookup field. Here's a visual:

 

hardware and asset relation

 

I'm hoping to write a trigger that fires when an Asset's AccountID changes that would:

 

  1. Check if there's an Associated_Product__c id that matches the Asset's ID that just changed
  2. If so, set the Hardware_Information__c's AccountId equal to the new Asset's ID
  3. If not, do nothing

This would essentially just make it so the Hardware Info follows its Asset when the Asset gets moved. I found this post which seems to be a great starting point. What do y'all think?

 

Thanks!!

 

-Jake

WhyserWhyser

Hope this is what you're looking for:

 

trigger AccountChangeOnAsset_Trigger on Asset( after update )
{
  for ( Asset a : Trigger.new )
  {
    // Check to see that the Account ID has changed
    if ( a.AccountId != Trigger.oldMap.get( a.Id ).AccountId )
    {
      // If we get here, then the Account ID has changed
      // Check to see if there are any Hardware_Information__c related to the Asset
      List< Hardware_Information__c > hiList = [select id, Associated_Product__c, Account__c from Hardware_Information__c where Associated_Product__c = :a.Product2Id];

      if ( hiList.size() > 0 )
      {
        // Update the returned values with the new Account Id
        for ( Hardware_Information__c hi : hiList )
        {
          hi.Account__c = a.AccountId;
        }
       
        // now update the list
        update hiList;
      }
    }
  }
}

JakesterJakester

Thank you, thank you, thank you for your help. It doesn't seem to be working yet. The first issue was all me: I used to have the Account__c field on the Hardware_Information__c object set to be master/detail, which of course means that it can't be changed once it's first set. So, I removed that field and created a new field called Account_LU__c which is a lookup to the Account object. I replaced the two references to Account__c with Account_LU__c. The System Log returns the following, so I know it's getting as far as knowing that the AccountId changed on the asset:

1 most expensive SOQL operations: Trigger.AccountChangeOnAsset_Trigger: line 10, column 48: [select id, Associated_Product__c, Account_LU__c from Hardware_Information__c where Associated_Product__c = :a.Product2Id]: executed 1 time in 4 ms

 

 Any thoughts on how I troubleshoot why it's not changing the ID on the Hardware_Information__c table?

 

 

 

 

WhyserWhyser

So it's getting stuck when it's trying to query the Hardware_Information__c object?
I'm not quite understanding what the error is that you posted, I've never seen an error where it talks about expensive SOQL operations. Are you sure there are not any other errors involved?

 

Maybe you should run some sample queries on the 'select id, Associated_Product__c, Account_LU__c from Hardware_Information__c where Associated_Product__c = :a.Product2Id' where you replace a.Product2Id with a sample Product Id just to make sure that it's working properly. Otherwise, the code is not that complex, so I can't really see what's going wrong.

JakesterJakester

Ok, so when I put this into the System Log:

 

select id, Associated_Product__c, Account_LU__c from Hardware_Information__c where Associated_Product__c = '02iS0000000Fq5y'

 

I get this:

 

 

14:50:09 ERROR - Compile error: unexpected token: select 14:50:20 DEBUG - Executing: select id, Associated_Product__c, Account_LU__c from Hardware_Information__c where Associated_Product__c = '02iS0000000Fq5y' 14:50:20 INFO - Cumulative profiling information: No profiling information for SOQL operations. No profiling information for SOSL operations. No profiling information for DML operations. No profiling information for method invocations. 14:50:20 ERROR - Compile error: unexpected token: select

 

 

I also tried entering the ID with double quotes and without anything surrounding it, and I always get the same message. Why wouldn't it like a select statement?

WhyserWhyser

I see a Compile error?

 

There must be something wrong with your code, when you try to save it you should be getting an error indicating what the issue is. (If you're using eclipse, this should be a tab called Problems).

 

Can you paste your code?

 

Another thing I noticed is that the ID you're trying to pass into the Hardware_Information__c.Associated_Product__c field is NOT a product2 ID. Product2 IDs start with 01t whereas the ID you're passing in starts with 02i. What kind of ID are you trying to pass in exactly? Is it the same kind of ID as the product2Id on the Asset?

Message Edited by Whyser on 02-26-2009 03:04 PM
JakesterJakester

Sure thing, but I only changed the Account__c to be Account_LU__c:

 

trigger AccountChangeOnAsset_Trigger on Asset( after update ) { for ( Asset a : Trigger.new ) { // Check to see that the Account ID has changed if ( a.AccountId != Trigger.oldMap.get( a.Id ).AccountId ) { // If we get here, then the Account ID has changed // Check to see if there are any Hardware_Information__c related to the Asset List< Hardware_Information__c > hiList = [select id, Associated_Product__c, Account_LU__c from Hardware_Information__c where Associated_Product__c = :a.Product2Id]; if ( hiList.size() > 0 ) { // Update the returned values with the new Account Id for ( Hardware_Information__c hi : hiList ) { hi.Account_LU__c = a.AccountId; } // now update the list update hiList; } } } }

 

 

 

 

WhyserWhyser

I'm very baffled by the compile error around the select statement.

 

Before running the query, can you insert a couple of lines?

 

System.debug( a.Product2Id + '\n\n' );
System.debug( [select id, Associated_Product__c, Account_LU__c from Hardware_Information__c where Associated_Product__c = :a.Product2Id] );

 

So hopefully these statements will run before we hit the error, maybe this might help us figure out what's going on.

Just to be clear, you have no issues saving and compiling the code, correct?

JakesterJakester

Yes, it's always saved and compiled just fine. Those dang smileys cropped in again, so just to be sure I did what you wanted, here's the updated code:

 

trigger AccountChangeOnAsset_Trigger on Asset( after update ) { for ( Asset a : Trigger.new ) { // Check to see that the Account ID has changed if ( a.AccountId != Trigger.oldMap.get( a.Id ).AccountId ) { System.debug( a.Product2Id + '\n\n') ; System.debug( [select id, Associated_Product__c, Account_LU__c from Hardware_Information__c where Associated_Product__c = :a.Product2Id] ); // If we get here, then the Account ID has changed // Check to see if there are any Hardware_Information__c related to the Asset List< Hardware_Information__c > hiList = [select id, Associated_Product__c, Account_LU__c from Hardware_Information__c where Associated_Product__c = :a.Product2Id]; if ( hiList.size() > 0 ) { // Update the returned values with the new Account Id for ( Hardware_Information__c hi : hiList ) { hi.Account_LU__c = a.AccountId; } // now update the list update hiList; } } } }

 

 When I run this, I can't find anything in the System Log. Not even what I used to see and included in my first reply. I must be doing something wrong. The log category I used to see messages in was the Database category, and I previously had the Log level at Error. I have since tried setting it to Finest and checked Database, Apex Code, and Apex Profiling, and I'm not seeing anything. Sorry if I'm doing something dumb here...

 

 

WhyserWhyser

just out of curiousity, how are you testing this?

 

I wrote a sample test code for you (you will have to fill in the product ID yourself )

 

static testMethod void test1() { Id Product2Id = insert_Product_Id_of_choice_here; Account acct1 = new Account( Name = 'acct1'); insert acct1; Account acct2 = new Account( Name = 'acct2'); insert acct2; Asset asst = new Asset( Name = 'testAsset', AccountId = acct1.Id, Product2Id = Product2Id ); insert asst; Hardware_Information__c hi = new Hardware_Information__c( Name = 'Some generic Name', Account_LU__c = acct1.Id, Associated_Product__c = Product2Id ); insert Hardware_Information__c; // Now update the asset with the acct2 ID // it SHOULD fire the trigger asst.AccountId = acct2.Id; update asst;

 

hi = [select id, Account_LU__c, Associated_Product__c from Hardware_Information__c where id = :hi.Id];

// Check to make sure the Account_LU__c was updated

// If this part fails it will return an exception

System.assert( hi.Account_LU__c == acct2.Id, 'Trigger did not work' ); }

 

 

You will have to put this into an APEX class and then you'll have to run the test... good luck.

Message Edited by Whyser on 02-26-2009 04:18 PM
JakesterJakester

Thank you again - I really, really appreciate your help. So I pasted this trigger in, and I found one tiny correction that I think I did right: I changed "insert Hardware_Information__c to "insert hi" and I also removed the Name = 'Some generic Name', because Hardware_Information__c is an auto-numbering object. When I click Validate on it in the Eclipse IDE, I get the following error:

 

 AccountChangeOnAsset_Test.myUnitTest System.DmlException: Insert failed. First exception on row 0; first error: FIELD_INTEGRITY_EXCEPTION, Associated Product: id value of incorrect type: 01t500000016su8AAA: [Associated_Product__c]

 

Could this be because I'm using a 15 digit ID?

 

Here's my code:

 

@isTest private class AccountChangeOnAsset_Test { static testMethod void myUnitTest() { Id Product2Id = '01t500000016su8'; Account acct1 = new Account( Name = 'acct1'); insert acct1; Account acct2 = new Account( Name = 'acct2'); insert acct2; Asset asst = new Asset( Name = 'testAsset', AccountId = acct1.Id, Product2Id = Product2Id ); insert asst; Hardware_Information__c hi = new Hardware_Information__c( Account_LU__c = acct1.Id, Associated_Product__c = Product2Id ); insert hi; // Now update the asset with the acct2 ID // it SHOULD fire the trigger asst.AccountId = acct2.Id; update asst; hi = [select id, Account_LU__c, Associated_Product__c from Hardware_Information__c where id = :hi.Id]; // Check to make sure the Account_LU__c was updated // If this part fails it will return an exception System.assert( hi.Account_LU__c == acct2.Id, 'Trigger did not work' ); } }

 

WhyserWhyser

Hey Jakester,

 

No, your Product2Id value is just fine. Just think, it worked when creating the asset, so it should have worked creating the Hardware_Information__c object.

And thanks for pointing out my little error, good catch.

 

This poses a very interesting problem. I think what you have to do is look at your custom object Hardware_Information__c and take a specific look at what kind of field Associated_Product__c is exactly. Is it a lookup field to the Product table? If not, I can see why your code is failing, and if that's the case, we're going to have to figure out some way to re-do this code because I'm not sure how the Associated_Product__c is related to the Asset.

 

My guess is that maybe Associated_Product__c is pointing to an Asset rather than a Product, and I think my assumption is correct based off oif the ID you gave me in message 5. 02i is an Asset ID.

 

IF this is the case, then you would simply need to change your query in the trigger to:

 

List< Hardware_Information__c > hiList = [select id, Associated_Product__c, Account_LU__c from Hardware_Information__c where Associated_Product__c = :a.Id];

 

And you'll have to change your test method line to:

 

Hardware_Information__c hi = new Hardware_Information__c ( Account_LU__c = acct1.Id, Associated_Product__c = asst.Id );

JakesterJakester

HALLELUJAH!!

 

It worked!! I made exactly the changes you gave me in the last post. So sorry I didn't make it clear how the tables were related - I think if I had done that your code would have been perfect initially. I really, really appreciate your help. This has been a huge thorn in our side as a company and it's going to make a huge difference in our data integrity. You, sir, rock. :smileyvery-happy: