locked
Need Expert: Account Name on Contact Phone Call RRS feed

  • Question

  • I am new to CRM and have been able to figure out everything up to now. I have read so many post and internet post and tried them. I have watched some many videos. It seems it should be easy. The contact record has the ParentCustomerID, and ParentCustomerName that holds the account if there is one associated. Now I am just totally confused on the required steps.

    Requirement: - I need Account Name to be displayed on the contact level phone call form and saved in phone call table so that it can be visible in the phone call view.

    I have in Phone Call N:1 Relationship field str_companyid (lookup) primary Entity is Account with Referential behavior.

    I tried a Phone Call N:1 Relationship field new_companystring (lookup) primary Entity is Contact with Referential behavior. I came to the conclusion that this is not a valid approach. Let me know if incorrect.

    Do I need a N:N instead?

    I have added the str_companyid field to the form. I went to the "Create a phone call for a contact" workflow process. On the "Create PhoneCall" step I have added the dynamic field {Company(Contact)}. After save and publishes; I created a phone call and it isn't populated.

    I have tried different Web Resource JS. I have added the JS in the onload of the form properties.  

    Why doesn't something as easy as this work? I can't seem to get the retrieveRecord to work. I  have also tried the xmlHttpObject object but it returns 0.

    Can someone help assist me on what I am missing? What are the complete steps to accomplish this?


    function PopulateCompanyName()
    {

        //get group GUID
        if (Xrm.Page.getAttribute("to").getValue()[0].id != null) {

            var lookup = Xrm.Page.getAttribute("to").getValue();

            alert(lookup[0].id);
            alert(lookup[0].typename);
            alert(lookup[0].name);

            alert(lookup);

            SDK.JQuery.retrieveRecord(lookup[0].id,
                lookup[0].typename,
                "ParentCustomerID",
                null,
                function (lookup) {
                    Xrm.Page.getAttribute("Company").setValue(lookup[0].str_companyid);
             });
        }

        else {
            Xrm.Page.getAttribute("str_companyid").setValue(null);
        }
    }

    -------------------------------

    function GetCompany()

    ///Get lookup ID

    {
    alert("I am Here");
     var lookupfield = Xrm.Page.getAttribute("to").getValue();
     if (lookupfield != null && lookupfield [0] != null)
     {
     var householdlookupvalue = lookupfield [0].id;
     }
     else
     {
     var householdlookupvalue = " ";
     }
    alert("I am here2");
    alert(householdlookupvalue);
    }

    // Prepare variables for a contact to retrieve.
     var authenticationHeader = Xrm.Page.context.getAuthenticationHeader();

    // Prepare the SOAP message.
     var xml = ""+
     ""+
     authenticationHeader+
     ""+
     ""+
     "contact"+
     ""+lookupfield [0].id+""+
     ""+
     ""+
     "parentcustomerid"+
     ""+
     ""+
     ""+
     ""+
     "";
    alert(xml );
    // Prepare the xmlHttpObject and send the request.
     var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
     xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
     xHReq.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/Retrieve");
     xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
     xHReq.setRequestHeader("Content-Length", xml.length);
     xHReq.send(xml);

    // Capture the result.
     var resultXml = xHReq.responseXML;
    alert("at results");
    var errorCount = resultXml.selectNodes('//error').length;
    alert("errorCount " + errorCount); ////////////////////////////////////returns 0; it shouldn't
    alert("After the result XML "+resultXml .toString() + " ::::");

    // Check for errors.
     var errorCount = resultXml.selectNodes('//error').length;
     if (errorCount != 0)
     {

    }
     // Display the retrieved value.
     else
     {

    //Create an array to set as the DataValue for the lookup control.
     var lookupData = new Array();

    //Create an Object add to the array.
     var lookupItem= new Object();

    //Set the id, typename, and name properties to the object.
     lookupItem.id = resultXml.selectSingleNode("//q1:parentcustomerid").nodeTypedValue;
     lookupItem.entityType = 'account';
     lookupItem.name = resultXml.selectSingleNode("//q1:parentcustomerid").getAttribute("name");
     // Add the object to the array.
     lookupData[0] = lookupItem;
    alert(lookupitem.name)
    // Set the value of the lookup field to the value of the array.
     Xrm.Page.getAttribute("str_companyid").setValue(lookupData);
     }


        var contact = new Array();
        contact = Xrm.Page.getAttribute("to").getValue();
    alert("I am here");
    alert(contact);
        if (contact == null || contact[0].entityType != "contact" || contact.length > 1) {
            return;
        }
    alert("inside if")
        var serverUrl = Xrm.Page.context.getClientUrl();
        var oDataSelect = serverUrl + "/XRMServices/2011/OrganizationData.svc/ContactSet?$select=ParentCustomerId&$filter=ContactId eq guid'" + contact[0].id + "'";

        var retrieveReq = new XMLHttpRequest();
        retrieveReq.open("GET", oDataSelect, false);
        retrieveReq.setRequestHeader("Accept", "application/json");
        retrieveReq.setRequestHeader("Content-Type", "application/json;charset=utf-8");
        retrieveReq.onreadystatechange = function () {
            GetContactData(this);
        };
        retrieveReq.send();
    }

    Sunday, June 15, 2014 5:06 PM

All replies

  • Can you post a screenshot indicating your expected result?

    As I understood you just want the parent account name of the contact selected inside the phone call, correct?


    My blog: www.crmanswers.net - Rockstar 365 Profile

    Sunday, June 15, 2014 6:15 PM
  • Hopefully what I have below helps. Yes I want it to return was is in the ParentCustomerName that corresponds to the ParentCustomerID which equals the accountid on the account view.

    As usual they want this by morning for the Reps on some new campaigns that were executed. Any guidance is totally appreciated. :)

    Bad news; It will not let me submit images because they haven't verified my account. I have a word document with the images but I don't see where I can upload it. Is there a way to send it to your blog?

    Theresa 

    Sunday, June 15, 2014 6:46 PM
  • you can send it to myname.mysurname(at)gmail(dot)com
    I think this can be solved with a workflow. Inside the phone call form, the field that will hold the value is a lookup or a text field?

    My blog: www.crmanswers.net - Rockstar 365 Profile


    Sunday, June 15, 2014 6:57 PM
  • It seems I can't send a link or put an image in here with me being new. I need to earn points first.

    I agree; I thought the workflow would work but it doesn't. I was using a lookup but it can be text field. Do I have this setup incorrectly below? What type of custom field should I use and if related how should it be related to get the right field in the drop down when on the workflow form?

    -----------

    I have in Phone Call N:1 Relationship field str_companyid (lookup) primary Entity is Account with Referential behavior.

    I tried a Phone Call N:1 Relationship field new_companystring (lookup) primary Entity is Contact with Referential behavior. I came to the conclusion that this is not a valid approach. Let me know if incorrect.

    Do I need a N:N instead?

    I have added the str_companyid field to the form. I went to the "Create a phone call for a contact" workflow process. On the "Create PhoneCall" step I have added the dynamic field {Company(Contact)}. After save and publishes; I created a phone call and it isn't populated.


    • Edited by T_Wadezone Sunday, June 15, 2014 7:26 PM
    Sunday, June 15, 2014 7:19 PM
  • Hi,
    I checked and you can't do this with a standard workflow, this because the recipient field accept multiple records, so the workflow designer doesn't offer you the choice to select the parent contact.
    you can handle this is with javascript (to display in real time the value), you need to add the script inside the onload (function onLoadPhoneCall) and inside the onchange for the recipient (onChangeRecipient)

    I'm assuming that your lookup field on phone call form pointing to Account entity is called str_companyid

    EDIT: I changed the code because contained small typo, please use the current version

    function onLoadPhoneCall() {
        if (Xrm.Page.ui.getFormType() == 1) {
            setToParentAccount();
        }
    }
    
    function onChangeRecipient() {
        setToParentAccount();
    }
    
    
    function setToParentAccount() {
        // set only if to Field (Recipient) has 1 record and is a contact
        if (Xrm.Page.getAttribute("to").getValue() != null) {
            var recipient = Xrm.Page.getAttribute("to").getValue();
            if (recipient.length == 1 && recipient[0].entityType == "contact") {
    
            var contactId = recipient[0].id;
                var serverUrl;
                if (Xrm.Page.context.getClientUrl !== undefined) {
                    serverUrl = Xrm.Page.context.getClientUrl();
                } else {
                    serverUrl = Xrm.Page.context.getServerUrl();
                }
    
                var ODataPath = serverUrl + "/XRMServices/2011/OrganizationData.svc"; 
                var contactRequest = new XMLHttpRequest();
                contactRequest.open("GET", ODataPath + "/ContactSet(guid'" + contactId + "')", false); 
                contactRequest.setRequestHeader("Accept", "application/json"); 
                contactRequest.setRequestHeader("Content-Type", "application/json; charset=utf-8");
    
                contactRequest.send();
                if (contactRequest.status === 200) {
                    var retrievedContact = JSON.parse(contactRequest.responseText).d;
                    var parentAccount = retrievedContact.ParentCustomerId;
    
                    if (parentAccount.Id != null && parentAccount.LogicalName == "account") {
                        var newParentAccount = new Array();
                        newParentAccount[0] = new Object();
                        newParentAccount[0].id = parentAccount.Id;
                        newParentAccount[0].name = parentAccount.Name;
                        newParentAccount[0].entityType = parentAccount.LogicalName;
                        Xrm.Page.getAttribute("str_companyid").setValue(newParentAccount);
                    } else {
                        Xrm.Page.getAttribute("str_companyid").setValue(null);
                    }
                } else {
                    alert("error");
                }
            } else {
                Xrm.Page.getAttribute("str_companyid").setValue(null);
            }
        }
    }

    My blog: www.crmanswers.net - Rockstar 365 Profile





    Sunday, June 15, 2014 7:59 PM
  • ok. Thanks. 

    I was finding that it wasn't being fired after I added it to the onload of the form properties. I added a few alerts.  I am not sure I understand this check. Xrm.Page.ui.getFormType()  1 is showing as create. Is that create from the phone call process? My alert returned something like "function(){return this.$1K_1.Formtype}. Is this correct?

    What libraries do I need to have inserted in this form for this code to work? This is really my first time doing a JS so I may not have the right ones in place. Do I remove the dynamic yellow highlight from that field in the workflow?

    I apologize for such annoying questions but I am a newbie and trying to understand what it takes to do this type of work.

    Sunday, June 15, 2014 8:47 PM
  • the form type check is to run the code onload only when you create a new record, if you skip that check, the function will be executed also when a user open an existing record, it will set the value but after you get the prompt that you have unsaved changes always.

    You don't need other libraries to run my code, and you need to delete your workflow (or it will replace the value after the record is saved)

    It's not an annoying question, and you tried to find and build a solution by yourself before, newbie don't do that.


    My blog: www.crmanswers.net - Rockstar 365 Profile

    Sunday, June 15, 2014 8:56 PM
  • I figured that was the case on the form. Since I am like in a major debugging/testing phase I set my onload to setToParentAccount just so I can see what is going on.

    It seems we haven't upgraded the CRM in awhile. We are several Rollups behind and they will be upgrading in a couple of months. With that said I think what I am running into maybe related to this but not 100% sure. I put lots of alerts in place to watch it.

    I validated that the recipient is getting correct values.

    I got undefined on this piece of the code          
    recipient[0].entityType == "contact"

    If I changed it to use the typename then it returns "contact"    
    recipient[0].typename == "contact") 

    I haven't looked it up but I am assuming we have get the URL for the ODath Path to work. 

    Here is where I am sort of stuck
      if (parentAccount.Id != null && parentAccount.entityType == "account")
    The correct value is returned for the parentAccount.ID; I get undefined for the entityType. If I changed it to typename like I did above I still get undefined.

    Before calling that if statement I did a check on the parentAccount.Name and it does contain the right value. Any thoughts on what attribute I need to look at
    to see if it is account?

    Sunday, June 15, 2014 9:37 PM
  • EDIT: change to && parentAccount.LogicalName == "account")
    I don't know why you get undefined inside the line recipient[0].entityType because it's CRM 2011 syntax (typename is CRM 4.0 syntax and works until CRM 2011 but not 2013)

    My blog: www.crmanswers.net - Rockstar 365 Profile




    Sunday, June 15, 2014 9:44 PM
  • Bless you!; Bless you!. Thank you! THANK YOU for sticking with me on this. The logicalname worked. I am showing we are still on CRM 2011(5.0.9690.2243) (DB 5.0.9690) several behind.

    The entire setToParentAccount works. I have been working on this the entire weekend except for a few hours for sleep. I was sure I could get this on there but found it was a lot hard than I expected. I really appreciate you answering my questions. I will make sure I vote. I think I can take it from here to do everything I have to do to get this fulling in place. I would like to ask a few verification questions.

    1 - Do I need the onchangerecipient? I am not sure of when I would need it called. Unless this is related to my #2 issue.

    2 - Do I need to put this in the On Save in order for it to save it to the record? I did a test campaign and it wasn't populated. After I opened it then it got populated. 

    3 - Is there a way to run this through for everyone in an existing phone campaign that was already run on Friday or is it best to update it directly by SQL?

    Thank you again! I totally appreciate you helping on this. 

    Sunday, June 15, 2014 10:57 PM
  • 1) the onChangeRecipient is necessary if you want to refresh the parent account when a user change the contact inside the recipient, so he will see the new parent right away.

    2) if the parent account field is not readonly you don't need to put inside onsave event, onload and onchange are enough, if you want to make the field readonly you need to use setSubmitMode("always") 

    3) the problem with JavaScript is that is executed only when a form is opened, so manually you need to open all the phone calls. If you want to update all the existing phone campaign programmatically you need to write a console application in C# that will retrieve the phone calls and update the value, or writing a custom workflow activity (still with C#) that does the same code as the javascript and use inside an ondemand workflow (and after you run the ondemand workflow on the existing phone calls)

    direct update of SQL database is unsupported and can lead to various issues in the future.

    If I was you I will proceed creating a custom workflow activity.


    My blog: www.crmanswers.net - Rockstar 365 Profile

    Sunday, June 15, 2014 11:17 PM
  • That makes sense on the Change. 

    I put the workflow back to onLoadPhoneCall. I can't tell if the form check works. I am not sure how to test. When I did a campaign from start to end the phone record in the view doesn't show it populated. When I go open the record it populates the field and I save it; it will save. 

    I did a test again and what I found is that the record is created in the phonecall table but most of the data is not populated. The ActivityPointer table has the record with most of the data populated but I don't have a company field for a phone call type. When I opened the phone call record and it populated the field and I saved it; then the phone call record has all of the data. What am I missing about the workflow process or is this something crazy with how our CRM was configured?

    I must be totally clueless on how workflows and JS work.

    I have a workflow called "Create New Phone call for Contact". It has 1 step to "create" PhoneCall. Do workflows open forms when it does the create so that the onload would be triggered?

    Theresa


    • Edited by T_Wadezone Monday, June 16, 2014 12:59 AM
    Sunday, June 15, 2014 11:58 PM