Question

I want to be able to calculate and display on my contact form the most recent Actual End date of that contacts appointments.

The following query shows how I have achieved the same functionality against the Account Entity.

How to test what data is present in d.data.results when querying CRM 2011 AppointmentSet using JavaScript and REST OData

Now I have tried to do the same on contacts but regardingobjectid does not match against any contacts. So I'm asking how do I go about this.

Do I need to open and expand each partylist for the Organiser, Optional Attendees and Required Attendees? If so How would I go about creating the query for this? Using the $expand functionality?

Please help a troubled mind!

Bump!

Was it helpful?

Solution

Ok so I have been working on this issue for a few days now.

I found that it was possible to complete this task with the help of the following tool XRM Dynamics Tools to help generate my OData query code.

Essentially the problem I had was understanding how contacts were linked to the Appointment. Once I understood that all participants for an appointment would be contained in the "appointment_activity_parties" field of an Appointment I was able to see how to create a suitable query to handle this problem.

By choosing the activityid, actualEnd fields and using the expand functionality on the appointment_activity_parties, selecting the PartyId from this expanded field enabled me to check that the party type was a contact, that the contactId of the Party matched with the current contact we were viewing. This way I could count the total number of matches and record the most recent date of a completed appointment for that contact.

In the end I also broke the problem down into 2 queries. One for each year: current and previous. I added three new fields to the Contact form. Two that hold the integers for VisitsLastYear and VisitsThisYear and a lookup to hold a link to the Appointment as can be seen in the following screenshot:

enter image description here

My code follows:

/// <reference path="XrmPageTemplate.js" />
/// <reference path="JQuery.js" />
/// <reference path="SDK.REST.js" />
/// <reference path="json2.js" />
function HarrionAB_ContactForm_OnLoad() {

    // get the contact id from the page
    var contactId = Xrm.Page.data.entity.getId().replace("{", "").replace("}", "")
    // if we got a value
    if (contactId != "") {
        var currentYear = new Date().getFullYear();
        var query = "/AppointmentSet?";                                                                         // Appointments table
            query += "$select=ActualEnd,ActivityId,appointment_activity_parties/PartyId";                       // Select
            query += "&$expand=appointment_activity_parties";                                                   // Expand sub tables
            query += "&$filter=ActivityTypeCode eq 'appointment' and StateCode/Value eq 1 and ";                // Where

        CountVisitsThisYear(query, currentYear);
        CountVisitsLastYear(query, currentYear - 1);
    }
}

function CountVisitsThisYear(query, currentYear) {

    var start = currentYear.toString() + "-01-01T00:00:00";
    var end = currentYear.toString() + "-12-31T00:00:00";

    query += "ActualStart ge datetime'" + start + "' or ActualStart le datetime'" + start + "' and ";   // Where  
    query += "ActualEnd ge datetime'" + end + "' or ActualEnd le datetime'" + end + "'";                // Where

    // call function to execute the odata query
    ExecuteVisitsThisYearQuery(query);
}

function CountVisitsLastYear(query, lastYear) {

    var start = lastYear.toString() + "-01-01T00:00:00";
    var end = lastYear.toString() + "-12-31T00:00:00";
    query += "ActualStart ge datetime'" + start + "' or ActualStart le datetime'" + start + "' and ";   // Where  
    query += "ActualEnd ge datetime'" + end + "' or ActualEnd le datetime'" + end + "'";                // Where

    // call function to execute the odata query
    ExecuteVisitsLastYearQuery(query);
}

//
// ExecuteQuery executes the specified OData Query asyncronously
//
// NOTE: Requires JSON and jQuery libraries. Review this Microsoft MSDN article before 
//       using this script http://msdn.microsoft.com/en-us/library/gg328025.aspx
//
function ExecuteVisitsThisYearQuery(ODataQuery) {

    // get the server url
    var serverUrl = Xrm.Page.context.getServerUrl();

    // Adjust URL for differences between on premise and online 
    if (serverUrl.match(/\/$/)) {
        serverUrl = serverUrl.substring(0, serverUrl.length - 1);
    }

    var ODataURL = serverUrl + "/XRMServices/2011/OrganizationData.svc" + ODataQuery;

    $.ajax({
        type: "GET",
        contentType: "application/json; charset=utf-8",
        datatype: "json",
        url: ODataURL,
        beforeSend: function (XMLHttpRequest) {
            XMLHttpRequest.setRequestHeader("Accept", "application/json");
        },
        success: function (data, textStatus, XmlHttpRequest) {
            //
            // Handle result from successful execution
            //
            // e.g. data.d.results
            var contactId = Xrm.Page.data.entity.getId().replace("{", "").replace("}", "");
            var lastVisitDate;
            var activityId;

            var count = 0;
            // if we have results
            if (data.d.results.length > 0) {
                // loop through the appointment results
                for (i = 0; i < data.d.results.length; i++) {
                    // if we have results
                    if (data.d.results[i].appointment_activity_parties.results.length > 0) {
                        // loop through the appointment_activity_parties
                        for (j = 0; j < data.d.results[i].appointment_activity_parties.results.length; j++) {
                            // if the party id type is contact and the contact ids match
                            if (data.d.results[i].appointment_activity_parties.results[j].PartyId.LogicalName == "contact" && contactId.toLowerCase() == data.d.results[i].appointment_activity_parties.results[j].PartyId.Id.toLowerCase()) {
                                // if we have not got a date yet
                                if (lastVisitDate == null) {
                                    // set the date as this is the first date we found
                                    lastVisitDate = data.d.results[i].ActualEnd;
                                    activityId = data.d.results[i].ActivityId;
                                } else {
                                    // if the current date is < new date
                                    if (lastVisitDate < data.d.results[i].ActualEnd) {
                                        // reset the date as we have found a later one
                                        lastVisitDate = data.d.results[i].ActualEnd;
                                        activityId = data.d.results[i].ActivityId;
                                    }
                                }
                                ++count;
                            }
                        }
                    }
                }
            }

            Xrm.Page.getAttribute("new_visitsthisyear").setValue(count);
            // if we found a completed appointment
            if (count > 0) {
                SetLookup("new_lastvisitcompleted", activityId, ParseJsonDate(lastVisitDate).toString('dd/MM/yyyy'), "Appointment");
            }
        },
        error: function (XmlHttpRequest, textStatus, errorObject) {
            //
            // Handle result from unsuccessful execution
            //
            alert("OData Execution Error Occurred");
        }
    });
}

//
// ExecuteQuery executes the specified OData Query asyncronously
//
// NOTE: Requires JSON and jQuery libraries. Review this Microsoft MSDN article before 
//       using this script http://msdn.microsoft.com/en-us/library/gg328025.aspx
//
function ExecuteVisitsLastYearQuery(ODataQuery) {

    // get the server url
    var serverUrl = Xrm.Page.context.getServerUrl();

    // Adjust URL for differences between on premise and online 
    if (serverUrl.match(/\/$/)) {
        serverUrl = serverUrl.substring(0, serverUrl.length - 1);
    }

    var ODataURL = serverUrl + "/XRMServices/2011/OrganizationData.svc" + ODataQuery;

    $.ajax({
        type: "GET",
        contentType: "application/json; charset=utf-8",
        datatype: "json",
        url: ODataURL,
        beforeSend: function (XMLHttpRequest) {
            XMLHttpRequest.setRequestHeader("Accept", "application/json");
        },
        success: function (data, textStatus, XmlHttpRequest) {
            //
            // Handle result from successful execution
            //
            // e.g. data.d.results
            var contactId = Xrm.Page.data.entity.getId().replace("{", "").replace("}", "");

            var count = 0;
            // if we have results
            if (data.d.results.length > 0) {
                // loop through the appointment results
                for (i = 0; i < data.d.results.length; i++) {
                    // if we have results
                    if (data.d.results[i].appointment_activity_parties.results.length > 0) {
                        // loop through the appointment_activity_parties
                        for (j = 0; j < data.d.results[i].appointment_activity_parties.results.length; j++) {
                            // if the party id type is contact and the contact ids match
                            if (data.d.results[i].appointment_activity_parties.results[j].PartyId.LogicalName == "contact" && contactId.toLowerCase() == data.d.results[i].appointment_activity_parties.results[j].PartyId.Id.toLowerCase()) {
                                ++count;
                            }
                        }
                    }
                }
            }

            Xrm.Page.getAttribute("new_visitslastyear").setValue(count);
        },
        error: function (XmlHttpRequest, textStatus, errorObject) {
            //
            // Handle result from unsuccessful execution
            //
            alert("OData Execution Error Occurred");
        }
    });
}


// function to parse JSON date into JavaScript Date
function ParseJsonDate(jsonDate) {
    var offset = new Date().getTimezoneOffset() * 60000;
    var parts = /\/Date\((-?\d+)([+-]\d{2})?(\d{2})?.*/.exec(jsonDate);

    if (parts[2] == undefined)
        parts[2] = 0;

    if (parts[3] == undefined)
        parts[3] = 0;

    return new Date(+parts[1] + offset + parts[2] * 3600000 + parts[3] * 60000);
};

//function to create a lookup control
function SetLookup(fieldName, idValue, textValue, typeValue) {
    var value = new Array();
    value[0] = new Object();
    value[0].id = idValue;
    value[0].name = textValue;
    value[0].typename = typeValue;

    Xrm.Page.getAttribute(fieldName).setValue(value);
}


//
// Error Handler
//
function ErrorHandler(XMLHttpRequest, textStatus, errorObject)
{ alert("Error Occurred : " + textStatus + ": " + JSON.parse(XMLHttpRequest.responseText).error.message.value); }

Hope this helps anyone with similar issues.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top