+ Start a Discussion
shan876shan876 

SELF_REFERENCE_FROM_TRIGGER????

Hi:

  I have the following code, which when one creates a new quote then the Opportunity Products will insert into the quote lines... Here is the code:

I keep getting this error:

Error: Invalid Data.
Review all error messages below to correct your data.
Apex trigger updatepartner caused an unexpected exception, contact your administrator: updatepartner: execution of BeforeUpdate caused by: System.DmlException: Insert failed. First exception on row 0; first error: SELF_REFERENCE_FROM_TRIGGER, Object (id = a0NR0000000KhDw) is currently in trigger updatepartner, therefore it cannot recursively update itself: Trigger.updatepartner: line 30, column 12

 

trigger updatepartner on SFDC_520_Quote__c (before update) { //apex/editQuoteLines?id={!SFDC_520_Quote__c.Id}&reloadQuote=1 for (SFDC_520_Quote__c quote: Trigger.new) { // delete any existing quote lines OpportunityLineItem[] olist; olist = [Select Id, OpportunityId, SortOrder, PricebookEntryId, Quantity, TotalPrice, UnitPrice, ListPrice, ServiceDate, Description, CreatedDate, CreatedById, LastModifiedDate, LastModifiedById, SystemModstamp, IsDeleted , PricebookEntry.Name, PricebookEntry.Product2id From OpportunityLineItem where OpportunityId = :quote.Opportunity__c ]; // create new quote lines SFDC_520_QuoteLine__c[] qlines = new list<SFDC_520_QuoteLine__c>(); for ( OpportunityLineItem oitem : olist) { SFDC_520_QuoteLine__c ql = new SFDC_520_QuoteLine__c( Quote__c = quote.id, Sales_Discount__c = 0.0, Qty_Ordered__c = oitem.Quantity, Unit_Price__c = oitem.UnitPrice, Description__c = oitem.Description, ServiceDate__c = oitem.ServiceDate, Product2__c = oitem.PricebookEntry.Product2id ); qlines.add(ql); } delete quote.Quote_Lines__r; if ( qlines.size() > 0 ) { insert qlines; } } }

 This code use to be a link from the quote code from salesforce.com. But I need it to be done automatically instead of the user clicking the link from the quote screen after they create the quote...

See below:

 

public class salesQuotes { public SFDC_520_Quote__c quote { get; private set;} public SFDC_520_QuoteLine__c[] quoteLineItems { get; private set; } public Opportunity opp { get; private set; } public Boolean hasContact { get { return (opp.opportunityContactRoles.size() == 1);} } public Contact contact { get; private set; } public DateTime a3months{get;set;} private ApexPages.StandardController controller; // constructor, loads the quote and any opportunity lines void queryQuoteLines(id id) { quote = [ Select s.Opportunity__r.Pricebook2Id, Quote_Amount_rollup__c,LastmodifiedDate, (Select Unit_Price__c, Unit_Net_Price__c, ServiceDate__c, Sales_Discount__c, Quote__c, Qty_Ordered__c, Product2__c, Product2__r.Name, Name, Id, Ext_Price__c, Ext_Net_Price__c, Ext_Price_tmp__c, Description__c From Quote_Lines__r order by name ), s.Opportunity__r.HasOpportunityLineItem, s.Opportunity__r.Name, s.Name, s.Opportunity__r.Id, s.Opportunity__c From SFDC_520_Quote__c s where s.id = :id limit 1]; a3months = quote.lastmodifieddate; a3months = a3months.addMonths(3); quoteLineItems = quote.Quote_Lines__r; for ( SFDC_520_QuoteLine__c ql : quoteLineItems ) { ql.Ext_Price_tmp__c = ql.Ext_Net_Price__c; if ( ql.Sales_Discount__c == null ) ql.Sales_Discount__c = 0.0; } } public opportunity total { get { double amount = 0.0; for ( SFDC_520_QuoteLine__c ql : quoteLineItems ) { amount += ql.Unit_Price__c * ql.Qty_Ordered__c * (1-(ql.Sales_Discount__c/100)) ; } Opportunity ret = new Opportunity( amount= amount ); return ret; } } public pagereference CopyOperation() { // implement copy to and from opportunity given page parameters string reloadQuote = ApexPages.CurrentPage().getParameters().get('reloadQuote'); string reloadOpp = ApexPages.CurrentPage().getParameters().get('reloadOpp'); if ( reloadOpp != null ) { copyLineItemsFromQuoteToOppty(); return opportunityPR() ; } if ( reloadQuote != null ) { copyLineItemsFromOpptyToQuote( ); return quotePR(); } return null; } public pagereference recalc() { for ( SFDC_520_QuoteLine__c ql : quoteLineItems ) { ql.Ext_Price_tmp__c = ql.Unit_Price__c * ql.Qty_Ordered__c * (1-(ql.Sales_Discount__c/100)) ; // see if this is a new line, if so then, fill in a bit more info if ( ql.Product2__c != null && ql.product2__r == null ) { ql.product2__r = [ select id, name from Product2 where id = :ql.Product2__c limit 1]; //system.debug ( ql.product2__r ); } } return null; } id quoteid; public salesQuotes() { quoteid = ApexPages.CurrentPage().getParameters().get('id'); init(); } public salesQuotes(ApexPages.StandardController c) { controller = c; quoteid = c.getRecord().id; init(); } // load up quote lines, opportunity lines, opportunity details and contact info void init() { queryQuoteLines(quoteid); if ( quote.opportunity__c != null ) { /* Set the related opportunity with the result of the query that traverses to account for display of the name and down to get the primary contact role. */ opp = [select name, account.name, (select contact.name, contact.mailingStreet, contact.mailingcity, contact.mailingstate, contact.mailingpostalcode , contact.phone,contact.title,contact.fax,contact.email from opportunityContactRoles where isPrimary = true) from opportunity where id = :quote.opportunity__c]; if ( hasContact ) { contact = opp.opportunityContactRoles[0].contact; } } } /* The action method that will generate a PDF document from the QuotePDF page and attach it to the quote provided by the standard controller. Called by the action binding for the attachQuote page, this will do the work and take the user back to the quote detail page. */ public PageReference attachQuote() { /* Get the page definition */ PageReference pdfPage = new PageReference( '/apex/quotePDF' ); /* set the quote id on the page definition */ pdfPage.getParameters().put('id',quote.id); /* generate the pdf blob */ Blob pdfBlob = pdfPage.getContent(); /* create the attachment against the quote */ Attachment a = new Attachment(parentId = quote.id, name=quote.name + '.pdf', body = pdfBlob); /* insert the attachment */ insert a; /* send the user back to the quote detail page */ return controller.view(); } // copy lines from the oppportunity to this quote public void copyLineItemsFromOpptyToQuote() { // delete any existing quote lines OpportunityLineItem[] olist; olist = [Select Id, OpportunityId, SortOrder, PricebookEntryId, Quantity, TotalPrice, UnitPrice, ListPrice, ServiceDate, Description, CreatedDate, CreatedById, LastModifiedDate, LastModifiedById, SystemModstamp, IsDeleted , PricebookEntry.Name, PricebookEntry.Product2id From OpportunityLineItem where OpportunityId = :quote.Opportunity__c ]; // create new quote lines SFDC_520_QuoteLine__c[] qlines = new list<SFDC_520_QuoteLine__c>(); for ( OpportunityLineItem oitem : olist) { SFDC_520_QuoteLine__c ql = new SFDC_520_QuoteLine__c( Quote__c = quote.id, Sales_Discount__c = 0.0, Qty_Ordered__c = oitem.Quantity, Unit_Price__c = oitem.UnitPrice, Description__c = oitem.Description, ServiceDate__c = oitem.ServiceDate, Product2__c = oitem.PricebookEntry.Product2id //a3months = oitem.lastmodifieddate.addMonths(3) //a3months.addMonths(3) ); qlines.add(ql); } delete quote.Quote_Lines__r; if ( qlines.size() > 0 ) { insert qlines; } } void makeQuotePrimary() { sobject[] allquotes = Database.query( 'Select s.Opportunity__c, S.ID, s.name '+ ' From SFDC_520_Quote__c s where s.Opportunity__c = \''+ quote.Opportunity__c + '\' ' ); for ( sobject so : allquotes) { if ( so.get('Id') == quote.id ) { so.put('Primary__c',true); } else { so.put('Primary__c',false); } } update allquotes; } public void copyLineItemsFromQuoteToOppty() { // find the appropriate pricebookentries for each product2 id List<ID> productIdList = new List<ID>(); for (SFDC_520_QuoteLine__c q : quoteLineItems) { productIdList.add((id) q.get('Product2__c')); } List<PricebookEntry> priceBookEntries = [Select id, Product2Id, Pricebook2Id From PricebookEntry where pricebook2id = :quote.Opportunity__r.Pricebook2Id and product2id in :productIdList]; Map<Id,Id> productIdToPricebookEntryIdMap = new Map<Id,Id>(); for(PricebookEntry p : pricebookEntries) { productIdToPricebookEntryIdMap.put(p.product2Id, p.id); } // clear out old opportunity line items id opptyId = quote.Opportunity__r.id; List<OpportunityLineItem> oldLineItems = [select id from OpportunityLineItem where opportunityId = :opptyId]; delete oldLineItems; // insert new ones List<OpportunityLineItem> newLineItems = new List<OpportunityLineItem>(); for ( SFDC_520_QuoteLine__c s: quoteLineItems){ newLineItems.add(New OpportunityLineItem(opportunityId = opptyId, quantity = (double) s.get('Qty_ordered__c'), unitPrice = (Double) s.get('Unit_Net_Price__c'), pricebookEntryId = productIdToPricebookEntryIdMap.get((id)s.get('Product2__c')), serviceDate = (date)s.get('serviceDate__c'), description = (string)s.get('Description__c') )); } system.debug(newLineItems); insert newLineItems; makeQuotePrimary(); // since we just overwrote the opp } PageReference opportunityPR() { return new pagereference('/'+quote.Opportunity__c); } PageReference quotePR() { return new pagereference('/'+quote.id); } public list<SFDC_520_QuoteLine__c> todelete = new list<SFDC_520_QuoteLine__c>(); public PageReference del() { string delname = ApexPages.CurrentPage().getParameters().get('delname'); system.assert( delname != null ); integer gone = -1; integer i = 0; for ( i=0; i< quoteLineItems.size(); i++ ) { if (quoteLineItems[i].Name == delname) { gone = i; } } if ( gone >= 0) { todelete.add( quoteLineItems.remove(gone) ); } return null; } public PageReference save() { try { upsert quoteLineItems; if ( todelete.size() > 0 ) { delete todelete; } queryQuoteLines(quote.id); } catch ( DmlException exc) { ApexPages.addMessages(exc); return null; } return quotePR(); } /* TODO * public PageReference add() { return null;} */ public PageReference add() { // insert a new line, after user selects a product? SFDC_520_QuoteLine__c q = new SFDC_520_QuoteLine__c( Quote__c = quote.id, Unit_price__c = 0.0, qty_ordered__c = 0.0, sales_discount__c = 0.0 ) ; quoteLineItems.add ( q ); return null; } public PageReference reset() { queryQuoteLines(quote.id); return null; }

 

 

 

 

 

werewolfwerewolf
Do you perhaps have another trigger on insert of SFDC_520_QuoteLine__c which tries to update the parent SFDC_520_Quote__c, thereby causing this exception?
shan876shan876

Well see the scenario is that from the second code that I posted up above has everything that should be done to the quotes, I thought if I take that portion out and place it into a trigger that would do it on a fluy instead of a link calling a VF page and then refreshing the page to see the products it would work. But I guess it did not...

Any ideas of how I can call this

public void copyLineItemsFromQuoteToOppty() { <== the code is up above that is the original trigger..

 

from the trigger into a before insert, before update call??

werewolfwerewolf
Well, you can't do an update on the object that called the trigger.  That would cause an infinite loop.  So if you could massage that code such that it doesn't update the caller but updates the other quotes, then it'll work.  If you're in a before update trigger, you don't actually have to call update on the calling object anyway -- you're already in the middle of an update so you can just edit the objects directly in Trigger.new.