crmdynamics-crm-onlinedynamics-crm-2013

On Approval Of Quotation, Run Report, Generate PDF and Send an Email With PDF as attachment


I am using CRM ONLINE 2013.

How to automate below process?

  1. On Approval Of Quotation, Run Report.

  2. Generate PDF.

  3. Send an Email With PDF as attachment.

As I have gone through many forums for this topic, but creating a plugin code for generating Report PDF is not possible in CRM ONLINE.

What is the alternate way to do this..?


Solution

  • I have tried below code and it is working fine for me.

        <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
        <html xmlns="http://www.w3.org/1999/xhtml">
        <head>
        <title></title>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
        <script type="text/javascript">
            if (typeof (SDK) == "undefined")
            { SDK = { __namespace: true }; }
            SDK.JScriptRESTDataOperations = {
                _context: function () {
    
                    if (typeof GetGlobalContext != "undefined")
                    { return GetGlobalContext(); }
                    else {
                        if (typeof Xrm != "undefined") {
                            return Xrm.Page.context;
                        }
                        else { return new Error("Context is not available."); }
                    }
                },
                _getServerUrl: function () {
                    var serverUrl = this._context().getServerUrl()
                    if (serverUrl.match(/\/$/)) {
                        serverUrl = serverUrl.substring(0, serverUrl.length - 1);
                    }
                    return serverUrl;
                },
                _ODataPath: function () {
                    return this._getServerUrl() + "/XRMServices/2011/OrganizationData.svc/";
                },
                _errorHandler: function (req) {
                    return new Error("Error : " +
          req.status + ": " +
         req.statusText + ": " +
         JSON.parse(req.responseText).error.message.value);
                },
                _dateReviver: function (key, value) {
                    var a;
                    if (typeof value === 'string') {
                        a = /Date\(([-+]?\d+)\)/.exec(value);
                        if (a) {
                            return new Date(parseInt(value.replace("/Date(", "").replace(")/", ""), 10));
                        }
                    }
                    return value;
                },
                Create: function (object, type, successCallback, errorCallback) {
                    var req = new XMLHttpRequest();
                    req.open("POST", this._ODataPath() + type + "Set", true);
                    req.setRequestHeader("Accept", "application/json");
                    req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
                    req.onreadystatechange = function () {
                        if (this.readyState == 4 /* complete */) {
                            if (this.status == 201) {
                                successCallback(JSON.parse(this.responseText, SDK.JScriptRESTDataOperations._dateReviver).d);
                            }
                            else {
                                errorCallback(SDK.JScriptRESTDataOperations._errorHandler(this));
                            }
                        }
                    };
                    req.send(JSON.stringify(object));
                },
                Retrieve: function (id, type, successCallback, errorCallback) {
                    var req = new XMLHttpRequest();
                    req.open("GET", this._ODataPath() + type + "Set(guid'" + id + "')", true);
                    req.setRequestHeader("Accept", "application/json");
                    req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
                    req.onreadystatechange = function () {
                        if (this.readyState == 4 /* complete */) {
                            if (this.status == 200) {
                                successCallback(JSON.parse(this.responseText, SDK.JScriptRESTDataOperations._dateReviver).d);
                            }
                            else {
                                errorCallback(SDK.JScriptRESTDataOperations._errorHandler(this));
                            }
                        }
                    };
                    req.send();
                },
                Update: function (id, object, type, successCallback, errorCallback) {
                    var req = new XMLHttpRequest();
    
                    req.open("POST", this._ODataPath() + type + "Set(guid'" + id + "')", true);
                    req.setRequestHeader("Accept", "application/json");
                    req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
                    req.setRequestHeader("X-HTTP-Method", "MERGE");
                    req.onreadystatechange = function () {
                        if (this.readyState == 4 /* complete */) {
                            if (this.status == 204 || this.status == 1223) {
                                successCallback();
                            }
                            else {
                                errorCallback(SDK.JScriptRESTDataOperations._errorHandler(this));
                            }
                        }
                    };
                    req.send(JSON.stringify(object));
                },
                Delete: function (id, type, successCallback, errorCallback) {
                    var req = new XMLHttpRequest();
                    req.open("POST", this._ODataPath() + type + "Set(guid'" + id + "')", true);
                    req.setRequestHeader("Accept", "application/json");
                    req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
                    req.setRequestHeader("X-HTTP-Method", "DELETE");
                    req.onreadystatechange = function () {
                        if (this.readyState == 4 /* complete */) {
                            if (this.status == 204 || this.status == 1223) {
                                successCallback();
                            }
                            else {
                                errorCallback(SDK.JScriptRESTDataOperations._errorHandler(this));
                            }
                        }
                    };
                    req.send();
    
                },
                RetrieveMultiple: function (type, filter, successCallback, errorCallback) {
    
                    if (filter != null) {
                        filter = "?" + filter;
                    }
                    else { filter = ""; }
    
                    var req = new XMLHttpRequest();
                    req.open("GET", this._ODataPath() + type + "Set" + filter, true);
                    req.setRequestHeader("Accept", "application/json");
                    req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
                    req.onreadystatechange = function () {
                        if (this.readyState == 4 /* complete */) {
                            if (this.status == 200) {
                                successCallback(JSON.parse(this.responseText, SDK.JScriptRESTDataOperations._dateReviver).d.results);
                            }
                            else {
                                errorCallback(SDK.JScriptRESTDataOperations._errorHandler(this));
                            }
                        }
    
                    };
                    req.send();
    
    
                },
                __namespace: true
            };
        </script>
        <script type="text/javascript">
            //Create Email and link it with Order as Regarding field
            var Xrm;
            var email = new Object();
            var ownerID = "";
            var CustomerId = "";
            if (window.opener) { Xrm = window.opener.Xrm; }
            else if (window.parent) { Xrm = window.parent.Xrm; }
    
            //Get ownerid who send email of quotation to customer
            function GetOwnerID() {
                var owner = Xrm.Page.getAttribute("ownerid").getValue();
                ownerID = owner[0].id;
                var ownerName = owner[0].name;
                var entityType = owner[0].entityType;
    
                GetToEmailGUID();
            }
            //Get customerid who receive email of quotation from owner
            function GetToEmailGUID() {
                var Customer = Xrm.Page.getAttribute('customerid').getValue();
                CustomerId = Customer[0].id;
                var CustomerName = Customer[0].name;
                var entityType = Customer[0].entityType;
    
                //if CustomerId is type of "Account" then get Primary Contact id of that account 
                if (entityType == "account") {
                    var contact = Xrm.Page.getAttribute("customerid").getValue();
    
                    if (contact === null) return;
    
                    var serverUrl = Xrm.Page.context.getClientUrl();
                    var oDataSelect = serverUrl + "/XRMServices/2011/OrganizationData.svc/AccountSet(guid'" + contact[0].id + "')?$select=PrimaryContactId";
    
                    var req = new XMLHttpRequest();
                    req.open("GET", oDataSelect, false);
                    req.setRequestHeader("Accept", "application/json");
                    req.setRequestHeader("Content-Type", "application/json;charset=utf-8");
                    req.onreadystatechange = function () {
                        if (req.readyState === 4) {
                            if (req.status === 200) {
                                var retrieved = JSON.parse(req.responseText).d;
                                CustomerId = retrieved.PrimaryContactId.Id;
                            }
                            else {
                                alert(this.statusText);
                            }
                        }
                    };
                    req.send();
    
                }
            }
            function CreateEmail() {
                GetOwnerID();
                email.Subject = "Email with Report Attachment";
    
                //Set The current order as the Regarding object
                email.RegardingObjectId = {
    
                    Id: Xrm.Page.data.entity.getId(),    //Get the current entity Id , here OrderId
                    LogicalName: Xrm.Page.data.entity.getEntityName()//Get the current entity name, here it will be “salesOrder”
    
                };
                //Create Email Activity 
                SDK.JScriptRESTDataOperations.Create(email, "Email", EmailCallBack, function (error) { alert(error.message); });
            }
    
            // Email Call Back function
    
            function EmailCallBack(result) {
                email = result; // Set the email to result to use it later in email attachment for retrieving activity Id
                var activityPartyFrom = new Object();
    
                // Set the From party of the ActivityParty to relate an entity with Email From field
                activityPartyFrom.PartyId = {
                    Id: CustomerId, //"79EBDD26-FDBE-E311-8986-D89D6765B238",  // id of entity you want to associate this activity with.          
                    LogicalName: "contact"
                };
                // Set the "activity" of the ActivityParty
    
                activityPartyFrom.ActivityId = {
                    Id: result.ActivityId,
                    LogicalName: "email"
                };
    
                // Now set the participation type that describes the role of the party on the activity).
    
                activityPartyFrom.ParticipationTypeMask = { Value: 2 }; // 2 means ToRecipients
    
                // Create the from ActivityParty for the email 
    
                SDK.JScriptRESTDataOperations.Create(activityPartyFrom, "ActivityParty", ActivityPartyFromCallBack, function (error) { alert(error.message); });
    
                var activityPartyTo = new Object();
    
                // Set the From party of the ActivityParty to relate an entity with Email From field
                activityPartyTo.PartyId = {
                    Id: ownerID, //"79EBDD26-FDBE-E311-8986-D89D6765B238",  // id of entity you want to associate this activity with.          
                    LogicalName: "systemuser"
                };
    
                // Set the "activity" of the ActivityParty  
                activityPartyTo.ActivityId = {
                    Id: result.ActivityId,
                    LogicalName: "email"
                };
    
                // Now set the participation type that describes the role of the party on the activity).    
                activityPartyTo.ParticipationTypeMask = { Value: 1 }; // 1 means Sender
    
                // Create the from ActivityParty
    
                SDK.JScriptRESTDataOperations.Create(activityPartyTo, "ActivityParty", ActivityPartyToCallBack, function (error) { alert(error.message); });
            }
    
            //ActivityParty From Callback
    
            function ActivityPartyFromCallBack(result) {
            }
    
            //ActivityParty To Callback
    
            function ActivityPartyToCallBack(result) {
                GetReportId('Quotation');
            }
            //Create attachment for the created email
    
            function CreateEmailAttachment() {
                //get reporting session and use the params to convert a report in PDF
    
                var params = getReportingSession();
    
                //Email attachment parameters
    
                var activitymimeattachment = Object();
                activitymimeattachment.ObjectId = Object();
                activitymimeattachment.ObjectId.LogicalName = "email";
                activitymimeattachment.ObjectId.Id = email.ActivityId;
                activitymimeattachment.ObjectTypeCode = "email",
                    activitymimeattachment.Subject = "File Attachment";
                activitymimeattachment.Body = encodePdf(params);
                activitymimeattachment.FileName = "Report.pdf";
                activitymimeattachment.MimeType = "application/pdf";
    
                //Attachment call
                SDK.JScriptRESTDataOperations.Create(activitymimeattachment, "ActivityMimeAttachment", ActivityMimeAttachmentCallBack, function (error) { alert(error.message); });
            }
    
            //ActivityMimeAttachment CallBack function
    
            function ActivityMimeAttachmentCallBack(result) {
                var features = "location=no,menubar=no,status=no,toolbar=no,resizable=yes";
                var width = "800px";
                var height = "600px";
    
                window.open(Xrm.Page.context.getServerUrl() + "main.aspx?etc=" + 4202 + "&pagetype=entityrecord&id=" + email.ActivityId, "_blank", features);
    
                // To open window which works in outlook and IE both
                //openStdWin(Xrm.Page.context.getServerUrl() + "main.aspx?etc=" + 4202 + "&pagetype=entityrecord&id=" + email.ActivityId, "_blank", width, height, features);
            }
    
            //This method will get the reportId based on a report name that will be used in            getReportingSession() function
    
            function GetReportId(reportName) {
                var oDataSetName = "ReportSet";
                var columns = "ReportId";
                var filter = "Name eq '" + reportName + "'";
                retrieveMultiple(oDataSetName, columns, filter, onSuccess);
            }
    
            function retrieveMultiple(odataSetName, select, filter, successCallback) {
    
                var serverUrl = Xrm.Page.context.getServerUrl();
                var ODATA_ENDPOINT = "/XRMServices/2011/OrganizationData.svc";
                var odataUri = serverUrl + ODATA_ENDPOINT + "/" + odataSetName + "?";
    
                if (select) {
                    odataUri += "$select=" + select + "&";
                }
    
                if (filter) {
                    odataUri += "$filter=" + filter;
                }
    
                $.ajax({
                    type: "GET",
                    contentType: "application/json; charset=utf-8",
                    datatype: "json",
                    url: odataUri,
                    beforeSend: function (XMLHttpRequest) {
                        XMLHttpRequest.setRequestHeader("Accept", "application/json");
    
                    },
    
                    success: function (data) {
                        if (successCallback) {
                            if (data && data.d && data.d.results) {
                                successCallback(data.d.results);
                            }
                            else if (data && data.d) {
                                successCallback(data.d);
                            }
                            else {
                                successCallback(data);
                            }
                        }
                    },
                    error: function (XmlHttpRequest, errorThrown) {
                        if (XmlHttpRequest && XmlHttpRequest.responseText) {
                            alert("Error while retrieval ; Error – " + XmlHttpRequest.responseText);
                        }
                    }
    
                });
    
            }
    
            function onSuccess(data) {
                reportId = data[0].ReportId.replace('{', ").replace('}', ");
                CreateEmailAttachment(); // Create Email Attachment
            }
    
            //Gets the report contents
    
            function getReportingSession() {
                var pth = Xrm.Page.context.getServerUrl() + "/CRMReports/rsviewer/reportviewer.aspx";
                var retrieveEntityReq = new XMLHttpRequest();
                var Id = Xrm.Page.data.entity.getId();
                var quotationGUID = Id.replace('{', ""); //set this to selected quotation GUID
                quotationGUID = quotationGUID.replace('}', "");
    
                var reportName = "Quotation"; //set this to the report you are trying to download
                var reportID = "7C39D18F-1DC6-E311-8986-D89D6765B238"; //set this to the guid of the report you are trying to download
                var rptPathString = ""; //set this to the CRMF_Filtered parameter
                var strParameterXML = "<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'><entity name='quote'><all-attributes /><filter type='and'><condition attribute='quoteid' operator='eq' uitype='quote' value='" + quotationGUID + "' /> </filter></entity></fetch>";
                retrieveEntityReq.open("POST", pth, false);
                retrieveEntityReq.setRequestHeader("Accept", "*/*");
                retrieveEntityReq.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    
                rptPathString = "id=%7B" + reportID + "%7D&uniquename=" + Xrm.Page.context.getOrgUniqueName() + "&iscustomreport=true&reportnameonsrs=&reportName=" +
                                reportName + "&isScheduledReport=false&p:CRMAF_Filteredquote=" + strParameterXML;
                //remove the part starting from &p:salesorderid if your report has no parameters
    
                retrieveEntityReq.send(rptPathString);
    
                var x = retrieveEntityReq.responseText.indexOf("ReportSession=");
                var ret = new Array();
                ret[0] = retrieveEntityReq.responseText.substr(x + 14, retrieveEntityReq.responseText.indexOf("&", x) - x - 14); //the session id
                x = retrieveEntityReq.responseText.indexOf("ControlID=");
                ret[1] = retrieveEntityReq.responseText.substr(x + 10, retrieveEntityReq.responseText.indexOf("&", x) - x - 10); //the control id
    
                return ret;
            }
            var bdy = new Array();
            var bdyLen = 0;
            function concat2Bdy(x) {
                bdy[bdyLen] = x;
                bdyLen++;
            }
            function encodePdf(params) {
    
                bdy = new Array();
                bdyLen = 0;
    
                var retrieveEntityReq = new XMLHttpRequest();
                var pth = Xrm.Page.context.getServerUrl() + "/Reserved.ReportViewerWebControl.axd?ReportSession=" + params[0] +
                "&Culture=1033&CultureOverrides=True&UICulture=1033&UICultureOverrides=True&ReportStack=1&ControlID=" + params[1] +
                "&OpType=Export&FileName=Public&ContentDisposition=OnlyHtmlInline&Format=PDF";
                retrieveEntityReq.open("GET", pth, false);
                retrieveEntityReq.setRequestHeader("Accept", "*/*");
                retrieveEntityReq.send();
                BinaryToArray(retrieveEntityReq.responseBody);
    
                return encode64(bdy);
    
            }
    
            var StringMaker = function () {
    
                this.parts = [];
                this.length = 0;
                this.append = function (s) {
                    this.parts.push(s);
                    this.length += s.length;
                }
    
                this.prepend = function (s) {
                    this.parts.unshift(s);
                    this.length += s.length;
                }
    
                this.toString = function () {
                    return this.parts.join('');
                }
            }
    
            var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    
            function encode64(input) {
                var output = new StringMaker();
                var chr1, chr2, chr3;
                var enc1, enc2, enc3, enc4;
                var i = 0;
    
                while (i < input.length) {
                    chr1 = input[i++];
                    chr2 = input[i++];
                    chr3 = input[i++];
    
                    enc1 = chr1 >> 2;
                    enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
                    enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
                    enc4 = chr3 & 63;
    
                    if (isNaN(chr2)) {
                        enc3 = enc4 = 64;
    
                    } else if (isNaN(chr3)) {
                        enc4 = 64;
                    }
    
                    output.append(keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4));
                }
    
                return output.toString();
    
            }      
        </script>
        <script type="text/vbscript">
    
        Function BinaryToArray(Binary)
    
               Dim i
    
               ReDim byteArray(LenB(Binary))
    
               For i = 1 To LenB(Binary)
    
                     byteArray(i-1) = AscB(MidB(Binary, i, 1))
    
                     concat2Bdy(AscB(MidB(Binary, i, 1)))
    
             Next
    
              BinaryToArray = byteArray
    
         End Function
    
    
        </script>
    </head>
    <body>
        <input type="button" onclick="CreateEmail();" value="Attach Report" />
    </body>
    </html>