+ Start a Discussion
MigMig 

Need some help for a update Trigger functionnality

Code:
trigger getDiscountsonOpportunities on Opportunity (after insert, after update){
for (opportunity op : [Select Bureau__r.Discount__c From Opportunity where id in : trigger.new ]){

op.Discount__c= op.Bureau__r.Discount__c;
op.Auth_Inv_Bureau__c = 15 ;
update op ;
}
}

Hi,
I'm a newbie on Apex code and I really need some help to make an update after insert/update

I want to make this once I have save the record :
Opportunity.Discount__c  = Opportunity.Bureau__r.discount__c;

I don't have any compile error but I've got this when I try to test it :

Error: Invalid Data.
Review all error messages below to correct your data.
Apex trigger getDiscountsonOpportunities caused an unexpected exception, contact your administrator: getDiscountsonOpportunities: maximum trigger depth exceeded Opportunity trigger event bulk AfterUpdate for 006S00000025Mar Opportunity trigger event bulk AfterUpdate for 006S00000025Mar Opportunity trigger event bulk AfterUpdate for 006S00000025Mar Opportunity trigger event bulk AfterUpdate for 006S00000025Mar Opportunity trigger event bulk AfterUpdate for 006S00000025Mar Opportunity trigger event bulk AfterUpdate for 006S00000025Mar Opportunity trigger event bulk AfterUpdate .....

Can I have some examples of this quind of functionnality Only to update some fields in the same object ...
Thank you really really very much for your help !!!


Message Edited by Mig on 02-05-2008 08:37 AM
JonPJonP
Mig,

Your trigger fires every time an opportunity (or set of opportunities) is inserted or updated, and it in turn performs a new update of the opportunity.  When you update the opportunity in your code, your trigger fires a second time, and updates the opportunity again, firing your trigger again, and so on--until the Apex governor stops your code from running infinitely.

There are several strategies you can use to avoid this scenario:

1. Use a "before" trigger.  By firing before the changes to the opportunity are committed, you can simply change whatever values you need.  You don't even need your own update statement, as your code executes in the middle of an insert/update that is in progress.  Just make whatever changes are necessary.

2. Add a condition to the update, such that you only update an opportunity when its values need to change.  For instance, you could wrap "if (op.Discount__c != op.Bureau__r.Discount__c || op.Auth_Inv_bureau__c != 15) { ... }" around your code that modifies the opportunity.

3. Use a static class to maintain a list of the Ids of opportunities you've processed, and similarly to #2 add a condition to skip any opportunities with Ids already in your static class.  This resembles the singleton design pattern, except the lifecycle of the static class is the transaction in which your trigger fires.  (There's good examples for this in the Force.com Cookbook.)

One other item to note:  In Apex, you should almost never perform a DML statement inside a loop.  Instead, create a list to hold the objects you need to update, and use a single DML statement to perform the action at the end.  For instance:

Code:
...
// create list
Opportunity[] opportunitiesToUpdate = new Opportunity[0];

// perform looping action
for (Opportunity op : Trigger.new) {
   ...
   if (doUpdate) {
      // add object to update to list
      opportunitiesToUpdate.add( op );
   }
}

// if list is not empty, perform update
if (!opportunitiesToUpdate.isEmpty()) {
   update opportunitiesToUpdate;
}

 



MigMig
what a beautifuuuuuuuuuul explanation .... =D Thank you very much for all your topics !!! have now understood my issues. (I Like very much the Singleton design pattern explanation)

But still got a problem ...

I can now update any field I want. But when I try to update a field with a related Object field. It does nothing :(
Code:
trigger getDiscountsonOpportunities on Opportunity (before update, before insert){
 Opportunity[] opportunitiesToUpdate = new Opportunity[0];
 Boolean doUpdate = false ; 
 
 for (Opportunity op : Trigger.new) {
 op.Discount__c= op.Bureau__r.Discount__c; // Got the problem !!! Even if the Bureau__c field is filled out! 
       op.Auth_Inv_Bureau__c = 15 ;  // IT works fine !! 

      if (op.Auth_Inv_Bureau__c != null)
       doUpdate = true ; 
      if (doUpdate){
        opportunitiesToUpdate.add( op );
       }
 }
 // if list is not empty, perform update  // Thank you JonP
 if (!opportunitiesToUpdate.isEmpty()) {
      update opportunitiesToUpdate;
 }
}

 







Message Edited by Mig on 02-06-2008 01:27 AM
MigMig
I found how to do it ..

I save the ID of the field Bureau__c and then I made another loop with a query on the Bureau object by checking the ID and then I've got all the values I want to start my assignement  ...

I works really fine ... My first Apex query is a success thanks to you :)
It's really cool to find some nice SFDC devs in the Discussion boards ! Thank you again one more time !!

Mig
MigMig
Wel But still have another issue :

(I'm on Enterprise edition )

My trigger works fine in my Sandbox and once I have the package I would like to deploy it in my Salesforce....

I have already installed ANT  and all the libraries ....
Well, It works fine when I pick the package and deploy the package in a spring 08 sandbox But whitout spring 08 is it possible ?

Gonna try ... Thank you




Message Edited by Mig on 02-06-2008 07:26 AM
MigMig
Yep I saw that already ...And It seems that Salesforce required a Test coverage ...

I've got this ... like other people :
Test coverage of selected Apex Trigger is 0%, at least 1% test coverage is required.
Test coverage of selected Apex Class and Trigger is 0%, at least 75% test coverage is required.

Gonna take another look to the cook book and to the Guide... And try to make one... Thank you!


Thank you one more time JonP ... I will come shortly for other news ....


Kind regards,
Mig


Message Edited by Mig on 02-06-2008 08:52 AM
MigMig
Hi,

Wel I've got some news ...
My Test coverage is working fine I've got 82 % for the test coverage and 100% for the Trigger It's fine to me.

Next step : The deploiement :
I try to do it by Salesforce but I've got this error after checking all :
NullPointerException:
  org.eclipse.jface.operation.ModalContext.runInCurrentThread (ModalContext.java 369)
  org.eclipse.jface.operation.ModalContext.run (ModalContext.java 313)
  org.eclipse.jface.wizard.WizardDialog.run (WizardDialog.java 851)
  com.salesforce.toolkit.ui.wizards.deploy.DeploymentResultsPage.setVisible (DeploymentResultsPage.java 48)
  org.eclipse.jface.wizard.WizardDialog.updateForPage (WizardDialog.java 1056)
  org.eclipse.jface.wizard.WizardDialog.access$2 (WizardDialog.java 1038)
  org.eclipse.jface.wizard.WizardDialog$4.run (WizardDialog.java 1028)
  org.eclipse.swt.custom.BusyIndicator.showWhile (BusyIndicator.java 67)
  org.eclipse.jface.wizard.WizardDialog.showPage (WizardDialog.java 1026)
  org.eclipse.jface.wizard.WizardDialog.nextPressed (WizardDialog.java 757)
  org.eclipse.jface.wizard.WizardDialog.buttonPressed (WizardDialog.java 351)
  org.eclipse.jface.dialogs.Dialog$3.widgetSelected (Dialog.java 660)
  org.eclipse.swt.widgets.TypedListener.handleEvent (TypedListener.java 90)
  org.eclipse.swt.widgets.EventTable.sendEvent (EventTable.java 66)
  org.eclipse.swt.widgets.Widget.sendEvent (Widget.java 928)
  org.eclipse.swt.widgets.Display.runDeferredEvents (Display.java 3348)
  org.eclipse.swt.widgets.Display.readAndDispatch (Display.java 2968)
  org.eclipse.jface.window.Window.runEventLoop (Window.java 820)
  org.eclipse.jface.window.Window.open (Window.java 796)
  com.salesforce.toolkit.actions.DeploymentAction.run (DeploymentAction.java 70)
  org.eclipse.ui.internal.PluginAction.runWithEvent (PluginAction.java 254)
  org.eclipse.jface.action.ActionContributionItem.handleWidgetSelection (ActionContributionItem.java 539)
  org.eclipse.jface.action.ActionContributionItem.access$2 (ActionContributionItem.java 488)
  org.eclipse.jface.action.ActionContributionItem$5.handleEvent (ActionContributionItem.java 400)
  org.eclipse.swt.widgets.EventTable.sendEvent (EventTable.java 66)
  org.eclipse.swt.widgets.Widget.sendEvent (Widget.java 928)
  org.eclipse.swt.widgets.Display.runDeferredEvents (Display.java 3348)
  org.eclipse.swt.widgets.Display.readAndDispatch (Display.java 2968)
....



Gonna try to make it other way.

Thank you in advance for your Help :

Mig

MigMig
An update and It works  !!!! Yeiihhh  :D My trigger is working already in the production salesforce =)
Thank you for the Help ..


But I have a question It's not possible to deactivate the trigger in the Production ?

gonna check ..

Thank you
micwamicwa
I'm also new to Apex Code and I didn't find out how to achieve the 75% test coverage. How did you do that?
MigMig
Check the Link gived by JonP. and check the cookbook Take 2 3 hours to understand how that works ...

In 2 words : You have to make a test that make fire the Trigger ... Like a trigger emulation ... sort of ;)

My exampe :
Code:
public class TesAccountTrigger {
static void me()
{
System.debug('test');
}
static testMethod void myTest()
{
me();
Id [] aID = new Id [1];
Double a = 20;
Account acc = new Account( id=aId[0], Name='TESTCOVERAGE', Discount__c= a, Authorized__c=true);
insert acc;

Opportunity oppty ;
Date d = Date.valueof('2008-02-12');
oppty = new Opportunity(Bureau__c= acc.Id, Name='OpptyTESTCOVERAGE', StageName='TEST', CloseDate=d);
insert oppty ;

oppty.Bureau__c = acc.Discount__c;
oppty.Discount__c = 15 ;
update oppty;
// ... Other dummy tests ...
}
}

 well It works But it's maybe not the best way to do it ... Like I said I started apex since 2 days ... Not yet finished the cookbook neither the guide ...



Message Edited by Mig on 02-07-2008 06:27 AM
RedtagRedtag
I'm trying to do something similar. I'd love to see your complete code.