+ Start a Discussion
AntonyWarcAntonyWarc 

Lead assignment rules help. Apex trigger maybe?

Hi,

 

We have a 3rd party webserivce that send leads from our site to SF with Lead Owner already assigned based on some coded rules. We now want to add a level of lead assignment above what this can handle, so I wrote a lead assignment rule and have activated it.

 

The rules seem to be completley ignored as leads are coming in, but work if a lead is edited and saved ticking the "use active assignmnet rules" checkbox. (i.e the lead assignment crieria works, but its not being triggered)

 

So I thought a trigger to re-run lead assignment directly after a lead has been created would be the only solution, issue is I have no coding experience (aside from one easy update trigger some guys on here helped with!)

 

Can anyone help? Or if another solution exists that woudl be great too!

 

Antony

Best Answer chosen by Admin (Salesforce Developers) 
CheyneCheyne

You could use the AssignmentRuleHeader in an Apex trigger, as in this post:

 

http://salesforce.stackexchange.com/questions/13651/lead-assignment-rule-in-a-trigger

 

I assume you'll only want to reassign leads that came from your website, so you'll need a way to check that in your trigger. Assuming these leads have a source of "website", and drawing off of the example above, you could write something like

 

trigger LeadTrigger on Lead (after insert) {
    List<Lead> ls = new List<Lead>();

    for (Lead l : Trigger.new) {
        if (l.LeadSource = 'Website') {
            ls.add(new Lead(id = l.id));
        }
    }

    Database.DMLOptions dmo = new Database.DMLOptions();
    dmo.assignmentRuleHeader.useDefaultRule = true;
    Database.update(ls, dmo);
}

 If you're able to modify the code that is sending the leads from your site to Salesforce, you could set the AssignmentRuleHeader from that end as well.

All Answers

CheyneCheyne

You could use the AssignmentRuleHeader in an Apex trigger, as in this post:

 

http://salesforce.stackexchange.com/questions/13651/lead-assignment-rule-in-a-trigger

 

I assume you'll only want to reassign leads that came from your website, so you'll need a way to check that in your trigger. Assuming these leads have a source of "website", and drawing off of the example above, you could write something like

 

trigger LeadTrigger on Lead (after insert) {
    List<Lead> ls = new List<Lead>();

    for (Lead l : Trigger.new) {
        if (l.LeadSource = 'Website') {
            ls.add(new Lead(id = l.id));
        }
    }

    Database.DMLOptions dmo = new Database.DMLOptions();
    dmo.assignmentRuleHeader.useDefaultRule = true;
    Database.update(ls, dmo);
}

 If you're able to modify the code that is sending the leads from your site to Salesforce, you could set the AssignmentRuleHeader from that end as well.

This was selected as the best answer
Ashish_SFDCAshish_SFDC

Hi Antony,

 

When dealing with Web to Lead, when you are setting up your Web to Lead form, you can set the value of the field 'Lead Source' to a specific value. (In fact, you can have this field be a hidden field so no one evens sees it.)

Then, you can set up a Lead Assignment Rule which says if the Lead Source field is equal to 'Web', then have the Lead go to the Lead-Open Queue.

See the links below for further info,

 

http://developer.force.com/cookbook/recipe/running-case-assignment-rules-from-apex

 

dmo.assignmentRuleHeader.useDefaultRule = true;
http://salesforce.stackexchange.com/questions/13651/lead-assignment-rule-in-a-trigger

 

Regards,
Ashish

AntonyWarcAntonyWarc
Thanks Cheyne, I appreciate your help. Will get this looked into and test.

Only work around we'll need to think about is we have multiple Lead Sources coming form the web so will look at another field to match against in your IF statement.

Antony
AntonyWarcAntonyWarc
Thanks Ashish, issue is the webservice that pushes leads to SF is 3rd party and we cant edit any part of it (long story). Plus we have around 20-30 lead sources...

Thanks for your time!
CheyneCheyne

That shouldn't be a problem. You can check each of the lead sources in the if statement. Before your for loop, create a set of all the lead sources to check for, like so

 

Set<String> leadSources = new Set<String>{'Source 1', 'Source 2'};

 Then, your if statement would say

 

if (leadSources.contains(l.LeadSource))

 This way, your checking that the lead source matches any one of the lead sources that are coming in from the web.

AntonyWarcAntonyWarc
Hey Cheyne,

Thanks again for this. Issue we have with this is we hijack the lead source and populate it with UTM codes based on camapigns the marketing team sends out. I then have triggers that update secondary source fields to map these out to campaigns held on SF.

So I tried thinking of another common field all leads would have, the only one I can think of is CreatedBy, all leads are created by our user: Mr Webservice.

So I attempted to adjust your original code to:

trigger LeadAssnTrigger on Lead (after insert) {
List<Lead> ls = new List<Lead>();

for (Lead l : Trigger.new) {
if (l.CreatedByid= '00520000001AOZ1') {
ls.add(new Lead(id = l.id));
}
}

Database.DMLOptions dmo = new Database.DMLOptions();
dmo.assignmentRuleHeader.useDefaultRule = true;
Database.update(ls, dmo);
}

But get the error:

Error: Compile Error: Field is not writeable: Lead.CreatedById at line 5 column 13

Am I missing something? I didnt think I was trying to write to the CreatedByid, just use it to match in the If statement.

Apologies, I really am a novice at Apex.

Antony
CheyneCheyne

Your if statement is using the assignment operator, =, instead of the equality operator, ==. Try updating it to 

 

if (l.CreatedByid == '00520000001AOZ1') {

 I would also recommend querying for the record owner, instead of hardcoding the ID. Before your for loop, you would write

 

String userId = [SELECT Id FROM User WHERE username='webserviceUserName'].Id;

 Then you can check that l.createdByid == userId in your if statement.

AntonyWarcAntonyWarc
Thanks Cheyne, this has now at least saved. I'll build a test class and then give it a go!
AntonyWarcAntonyWarc
Me again Cheyne. Appreciate that you may ask me to politely leave you alone, but I'm lost building my test class. I assumed i would just do a @istest and copy the same code over. Of course this isnt the case!

Maybe I shouldn't be trying triggers at all!!

Antony
CheyneCheyne

The basic idea of the test class is to programmatically create a situation where your trigger will run, and then you check that you got the correct results. In your case, you'll need to use the System.runAs() method, so that you can create leads with the web service user and then check that the lead assignment rule was applied to them. So, you could write something along the lines of the following:

 

@isTest
private class TestLeadAssignmentTrigger {
  static testMethod void testLeadAssignmentTrigger() {
//This is the web service user that you will insert the lead as User u = [SELECT Id FROM User WHERE username='webserivceuser'];
//Create the lead sObject
Lead l = new Lead( LastName='Test' );
//Insert the lead as the web service user System.runAs(u) { insert l; } //This is the user that you expect the lead inserted above to be assigned to User checkUser = [SELECT Id FROM User WHERE username='newuser'];

//Check that the lead was actually reassigned System.assertEquals(checkUser.Id, l.CreatedById); } }

 

AntonyWarcAntonyWarc
Once again thank you so much for this. I've tweaked and run the test and got a fail. Not sure why the second id in the assert test is coming back null? 

Time Started 21/10/2013 15:07 Class TestLeadAssignmentTrigger Method Name testLeadAssignmentTrigger Pass/Fail Fail Error Message System.AssertException: Assertion Failed: Expected: 00520000001AOZ1AAO, Actual: null Stack Trace Class.TestLeadAssignmentTrigger.testLeadAssignmentTrigger: line 22, column 1 @isTest private class TestLeadAssignmentTrigger { static testMethod void testLeadAssignmentTrigger() { //This is the web service user that you will insert the lead as User u = [SELECT Id FROM User WHERE Name='Primalink Webservice']; //Create the lead sObject Lead l = new Lead( LastName='Test', Company='Ogilvy' ); //Insert the lead as the web service user System.runAs(u) { insert l; } //This is the user that you expect the lead inserted above to be assigned to User checkUser = [SELECT Id FROM User WHERE Name='Primalink Webservice']; //Check that the lead was actually reassigned System.assertEquals(checkUser.Id, l.createdbyid); } }

 

CheyneCheyne

I apologize, I made a mistake in the original test that I gave you. After you insert the lead, you need to query for that lead in order to see all of the data in it. Also, your assertion needs to check OwnerId, instead of CreatedById. So, at the end (replacing your current last line), you can write

 

l = [SELECT OwnerId FROM Lead WHERE Id = :l.Id];
System.assertEquals(checkUser.Id, l.OwnerId);

 Let me know if that solves it!

AntonyWarcAntonyWarc

Cheyne,

 

First of all really no need for your apologies. You have gone beyond amazing by helping us.

 

This has fixed it. Test passed and trigger now applied to my live SF instance. 

 

After 2 years of SF, I am now finally understanding the benefits of it being open source and am planning on learning Apex properly (I last programmed when VB was just VB!)

 

Once again a thousand thanks.

 

Antony

CheyneCheyne

Not a problem, glad I coud help :)