You need to sign in to do that
Don't have an account?
Writing a query for master-detail relationship in a trigger
Hi All,
I'm working with a couple of custom objects that have a master-detail relationship with one another. The master's api name is zqu_Quote__c and the detail's api name is zqu__QuoteCharge__c.
I'm trying to write a simple trigger that will query for the field "zqu__Discount__c" in the detail object and assign that value to the field Discount__c in the master object. Unfortunately, I'm having trouble accessing the master object in my query. My code is below - I think my issue has to do with the syntax I'm using to call for the ID of the zqu__Quote__c object. Any suggestions?
trigger DiscountUpdate on zqu__QuoteCharge__c (after insert) { list<QuoteCharges__c> myList = [select q.Id, q.zqu__Discount__c, q.zqu__Quote__r.Discount__c from zqu__QuoteCharge__c q where q.Quote__c =:quoteID]; for (QuoteCharge__c qc: myList) { qc.zqu__Quote__r.Discount__c = qc.zqu__Discount__c; } update mylist; }
You get this error because you haven't defined the "quoteID" yet.
I suppouse this is the Id of your header object.
Why don't you try with my second aproach? I think it is much more completed, and it works. I did something similar yesterday.
I this case you will fill a set with the header objects, then you can create your query and use
"q.Quote__c in :quoteIDSet"
and after that assign the ne value, add to the new list and finally, update the header object.
Let me know if you have any other problem.
All Answers
Hi,
Try to create a new list where you can add the object hat you have just modified.
After that, update this new list.
Something like:
List<QuoteCharge__c> newList = new List<QuoteCharge>();
for(QuoteCharge__c qc: mylist)
{
qc.discount = zqu_Discount;
newList.add(qc);
}
update newList;
If this doesn't work, you try:
Set<ID> headerObjectIdSet = new Set<ID>();
for(DetailObject__c iter : trigger.new)
headerObjectIdSet.add(iter.HeaderId);
List<HeaderObject> headerToUpdate = new List<HeaderObject>();
List<HeaderObject> headerList = [Select Discount from HeaderObject where Id in :headerObjectIdSet];
if(headerList != null)
{
for(HeaderObject header : headerList)
{
header.Discount = value;
headerToUpdate.add(header);
}
update header;
}
Hi Mariagus,
Thanks for the reply! I've added the changes you suggested in the first half like this:
(It was returning an invalid type error if i tried to make the list of type <QuoteCharge>, but i think this will work). I'm still returning an error for the final statement in my query, where I ask: where q.Quote__c =: quoteID. It's telling me it doesn't recognize the variable quoteID. Am I missing something syntactically here?
Thank you so much! I appreciate the help.
You get this error because you haven't defined the "quoteID" yet.
I suppouse this is the Id of your header object.
Why don't you try with my second aproach? I think it is much more completed, and it works. I did something similar yesterday.
I this case you will fill a set with the header objects, then you can create your query and use
"q.Quote__c in :quoteIDSet"
and after that assign the ne value, add to the new list and finally, update the header object.
Let me know if you have any other problem.
Looks like it's working now - or at least, the only error it's returning now is that i have 0% coverage for the trigger. I just need to write a unit test for this bugger, then I'll be able to deploy. Thank you so much for all the help!!! (and if you have a sample unit test you used for the trigger you built yesterday, I'm sure wayward google searchers who stumble upon this thread months from now would love to see it :) )
once i get this to successfully deploy, can i mail you a beer or something?
here's what I have now:
Hey!! You got it!!
We don't create a unit test just for a trigger. What we do is to create unit tests for our classes. Your trigger will be covered if one of these test insert the obeject (your trigger is after insert) So, if for example, you have a class where a method is to check the Discount__c value that after inserting a detial object, your test could be:
@isTest
private class myUnitTest
{
private testMethod static void test()
{
HeaderObject myHeaderObject = new HeaderObjec();
myHeaderObject.Name = 'myHeader';
//fill fields with values that you need
insert myHeaderObject;
DetailObject myDetailObject = new DetailObject();
myDetailObject.Name = 'myDetailObject';
//Don't forget link the child with the father
myDetailObject.HeaderObjectId = myHeaderObject.Id;
myDetailObject.Discount__c = 5;
//fill field with values that you need
insert myDetailObject;
//At this point, your trigger should be covered.
//Call to the method that you want to cover on your class
Decimal discountValue = MyClass.getMyHeaderObjectDiscountValue();
System.assertEquals(discountValue,5);
}
}
Of course, you can following calling to other methods on your class.
This should be enough for your test.
yep, definitely mailing a beer. I ended up writing one myself, and it turns out to be remarkably similar to what you've put down here. for what it's worth:
Good job :)