简体   繁体   中英

How to prevent Dynamics CRM 2015 from creating an opportunity when a lead is qualified?

Requirements when clicking the Qualify button in the Lead entity form:

  • Do not create an Opportunity
  • Retain original CRM qualify-lead JavaScript
  • Detect duplicates and show duplicate detection form for leads
  • Redirect to contact, either merged or created version, when done

The easiest approach is to create a plugin running on Pre-Validation for message "QualifyLead". In this plugin you simply have to set CreateOpportunity input property to false. So it would look like:

public void Execute(IServiceProvider serviceProvider)
{
    IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
    context.InputParameters["CreateOpportunity"] = false;
}

Or you can go with more fancy way:

public void Execute(IServiceProvider serviceProvider)
{
    IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
    var qualifyRequest = new QualifyLeadRequest();
    qualifyRequest.Parameters  = context.InputParameters;
    qualifyRequest.CreateOpportunity = false;
}

Remember that it should be Pre-Validation to work correctly. Doing it like that allows you to remain with existing "Qualify" button, without any JavaScript modifications.

So Pawel Gradecki already posted how to prevent CRM from creating an Opportunity when a Lead is qualified. The tricky part is to make the UI/client refresh or redirect to the contact, as CRM does nothing if no Opportunity is created.

Before we begin, Pawel pointed out that

some code is not supported, so be careful during upgrades

I don't have experience with any other versions than CRM 2015, but he writes that there are better ways to do this in CRM 2016, so upgrade if you can. This is a fix that's easy to implement now and easy to remove after you've upgraded.

Add a JavaScript-resource and register it in the Lead form's OnSave event. The code below is in TypeScript. TypeScript-output (js-version) is at the end of this answer.

function OnSave(executionContext: ExecutionContext | undefined) {
    let eventArgs = executionContext && executionContext.getEventArgs()
    if (!eventArgs || eventArgs.isDefaultPrevented() || eventArgs.getSaveMode() !== Xrm.SaveMode.qualify)
        return

    // Override the callback that's executed when the duplicate detection form is closed after selecting which contact to merge with.
    // This callback is not executed if the form is cancelled.
    let originalCallback = Mscrm.LeadCommandActions.performActionAfterHandleLeadDuplication
    Mscrm.LeadCommandActions.performActionAfterHandleLeadDuplication = (returnValue) => {
        originalCallback(returnValue)
        RedirectToContact()
    }

    // Because Opportunities isn't created, and CRM only redirects if an opportunity is created upon lead qualification,
    // we have to write custom code to redirect to the contact instead
    RedirectToContact()
}

// CRM doesn't tell us when the contact is created, since its qualifyLead callback does nothing unless it finds an opportunity to redirect to.
// This function tries to redirect whenever the contact is created
function RedirectToContact(retryCount = 0) {
    if (retryCount === 10)
        return Xrm.Utility.alertDialog("Could not redirect you to the contact. Perhaps something went wrong while CRM tried to create it. Please try again or contact the nerds in the IT department.")

    setTimeout(() => {
        if ($("iframe[src*=dup_warning]", parent.document).length)
            return // Return if the duplicate detection form is visible. This function is called again when it's closed

        let leadId = Xrm.Page.data.entity.getId()
        $.getJSON(Xrm.Page.context.getClientUrl() + `/XRMServices/2011/OrganizationData.svc/LeadSet(guid'${leadId}')?$select=ParentContactId`)
            .then(r => {
                if (!r.d.ParentContactId.Id)
                    return RedirectToContact(retryCount + 1)

                Xrm.Utility.openEntityForm("contact", r.d.ParentContactId.Id)
            })
            .fail((_, __, err) => Xrm.Utility.alertDialog(`Something went wrong. Please try again or contact the IT-department.\n\nGuru meditation:\n${err}`))
    }, 1000)
}

TypeScript definitions:

declare var Mscrm: Mscrm

interface Mscrm {
    LeadCommandActions: LeadCommandActions
}

interface LeadCommandActions {
    performActionAfterHandleLeadDuplication: { (returnValue: any): void }
}

declare var Xrm: Xrm

interface Xrm {
    Page: Page
    SaveMode: typeof SaveModeEnum
    Utility: Utility
}

interface Utility {
    alertDialog(message: string): void
    openEntityForm(name: string, id?: string): Object
}

interface ExecutionContext {
    getEventArgs(): SaveEventArgs
}

interface SaveEventArgs {
    getSaveMode(): SaveModeEnum
    isDefaultPrevented(): boolean
}

interface Page {
    context: Context
    data: Data
}

interface Context {
    getClientUrl(): string
}

interface Data {
    entity: Entity
}

interface Entity {
    getId(): string
}

declare enum SaveModeEnum {
    qualify
}

TypeScript-output:

function OnSave(executionContext) {
    var eventArgs = executionContext && executionContext.getEventArgs();
    if (!eventArgs || eventArgs.isDefaultPrevented() || eventArgs.getSaveMode() !== Xrm.SaveMode.qualify)
        return;
    var originalCallback = Mscrm.LeadCommandActions.performActionAfterHandleLeadDuplication;
    Mscrm.LeadCommandActions.performActionAfterHandleLeadDuplication = function (returnValue) {
        originalCallback(returnValue);
        RedirectToContact();
    };
    RedirectToContact();
}
function RedirectToContact(retryCount) {
    if (retryCount === void 0) { retryCount = 0; }
    if (retryCount === 10)
        return Xrm.Utility.alertDialog("Could not redirect you to the contact. Perhaps something went wrong while CRM tried to create it. Please try again or contact the nerds in the IT department.");
    setTimeout(function () {
        if ($("iframe[src*=dup_warning]", parent.document).length)
            return;
        var leadId = Xrm.Page.data.entity.getId();
        $.getJSON(Xrm.Page.context.getClientUrl() + ("/XRMServices/2011/OrganizationData.svc/LeadSet(guid'" + leadId + "')?$select=ParentContactId"))
            .then(function (r) {
            if (!r.d.ParentContactId.Id)
                return RedirectToContact(retryCount + 1);
            Xrm.Utility.openEntityForm("contact", r.d.ParentContactId.Id);
        })
            .fail(function (_, __, err) { return Xrm.Utility.alertDialog("Something went wrong. Please try again or contact the IT-department.\n\nGuru meditation:\n" + err); });
    }, 1000);
}

There is a fully functional and supported solution posted over at our Thrives blog: https://www.thrives.be/dynamics-crm/functional/lead-qualification-well-skip-that-opportunity .

Basically we combine the plugin modification as mentioned by Pawel with a Client Side redirect (using only supported JavaScript) afterwards:

function RefreshOnQualify(eventContext) {
    if (eventContext != null && eventContext.getEventArgs() != null) {
        if (eventContext.getEventArgs().getSaveMode() == 16) {
            setTimeout(function () {
                Xrm.Page.data.refresh(false).then(function () {
                    var contactId = Xrm.Page.getAttribute("parentcontactid").getValue();
                    if (contactId != null && contactId.length > 0) {
                        Xrm.Utility.openEntityForm(contactId[0].entityType, contactId[0].id)
                    }
                }, function (error) { console.log(error) });;
            }, 1500);
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM