This is the documentation for Clover Club 12.0.
Documentation for the upcoming version Rampur 13.0 can be found here.

Configure Account/Opportunity Integration Unified Interface

This page shows how to integrate Pricefx Unity to the MS Dynamics Account/Opportunity page using IFrame.

  1. Open MS Dynamics and locate the gear icon in the top-right corner of the interface.

  2. Click the gear icon to access the Advanced Settings menu.

  3. In the Settings dropdown, locate and select the Customizations option from the Customization list.

     

  4. In the Search field, type either “Opportunity” or “Account” to initiate a search.

  5. In the list, locate “Opportunity” or “Account”.

  6. Click Opportunity or Account which appeared in the list and click Forms.

     

  7. Select Form in which you want to add iFrame.
    The same library can be used for Account and Opportunity Pages.
    PFXRegisterListener and PFXInputsLookup must be unique for every library.

  8. Add JavaScript code to the MS Dynamics library.

    1. In the opened Form open the JavaScript library tab.

    2. Click Add Library.

    3. In the modal window, click New web resource.

    4. Fill in the form and upload the JavaScript file (Edit Code).

       

      var PFXRegisterListener = function () { //TODO: Change to unique name if (window.XMLHttpRequest) { //for browsers other than ie window.parent.parent.addEventListener("message", PFXInputsLookup, false); //TODO: change PFXInputsLookup } else { window.parent.parent.attachEvent("onmessage", PFXInputsLookup); //TODO: change PFXInputsLookup } window.parent.document.getElementById("IFRAME_<iframe name>").style.height = "1000px"; // TODO: Edit height if needed }; var PFXInputsLookup = function (event) { //TODO: Change to a unique name and update all occurrences if (event.origin != "https://<customer cluster domain name>") { //TODO: add customer cluster domain name return; } var jsonData = JSON.parse(event.data); var action = jsonData.action; var data = jsonData.data; var entity = parent.window.Xrm.Page.data.entity; switch (action) { case "getEntityInfo": console.log("..DYNAMICS.eventHandler getEntityInfo", action); var response = {}; response.entityName = entity.getEntityName(); response.id = entity.getId(); response.accountnumber = entity.attributes .get("accountnumber") .getValue(); event.source.postMessage(JSON.stringify(response), event.origin); break; case "setDashboardInputs": console.log("..DYNAMICS.eventHandler setDashboardInputs", action); var id = entity.getId(); data.fields.forEach(function (fieldName) { var attribute = entity.attributes.get(fieldName); if (attribute) { data[fieldName] = attribute.getValue(); } }); var response = {}; response.id = id; response.data = data; response.entityName = entity.getEntityName(); event.source.postMessage(JSON.stringify(response), event.origin); break; case "getPayload": console.debug("DYNAMICS - message received from PRICE FX", jsonData); var payload = {}; entity.attributes.forEach(function (attribute) { var attributeName = attribute.getName(); payload[attributeName] = attribute.getValue(); }); response.action = action; payload.id = id; payload.entityName = entity.getEntityName(); response.data = payload; event.source.postMessage(JSON.stringify(response), event.origin); break; case "getAccount": { console.log("..DYNAMICS.eventHandler getAccount", action); var account = parent.window.Xrm.Page.data.entity.attributes .get("parentaccountid") .getValue()[0]; if (account) { Xrm.WebApi.retrieveRecord( "account", account.id, "?$select=name,accountnumber" ).then((result) => { console.info("Successful get account", result); var accountNumber = result.accountnumber; if (!data.lineItemFields) { var entity = { id: id, data: data, action: action, accountnumber: accountNumber, entityName: parent.window.Xrm.Page.data.entity.getEntityName(), lineItems: [], customerName: result ? result.name : null, }; event.source.postMessage(JSON.stringify(entity), event.origin); } }); } break; } case "findOpportunities": console.log("..DYNAMICS.eventHandler findOpportunities", action); var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function () { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { var opportunities = []; var response = JSON.parse(xmlhttp.responseText); for (var i = 0; i < response.value.length; ++i) { var opportunity = response.value[i]; opportunities.push({ Id: "{" + opportunity.opportunityid + "}", Name: opportunity.name, }); } event.source.postMessage( JSON.stringify({ id: "1", data: opportunities }), event.origin ); } }; xmlhttp.open( "GET", "/api/data/V8.0/opportunities/?$select=name&$top=10&$filter=contains(name,'" + data.searchText + "')", true ); xmlhttp.send(); break; case "createNewQuote": console.log("..DYNAMICS.eventHandler createNewQuote", action); var id = entity.getId(); data.fields.forEach(function (item) { const foundItem = entity.attributes.get(item.id); if (foundItem) { item.value = foundItem.getValue(); } }); var account = parent.window.Xrm.Page.data.entity.attributes .get("parentaccountid") .getValue()[0]; if (account) { Xrm.WebApi.retrieveRecord( "account", account.id, "?$select=name,accountnumber" ).then((result) => { console.info("Successful get account", result); var accountNumber = result.accountnumber; if (!data.lineItemFields) { var entity = { id: id, data: data, action: action, accountnumber: accountNumber, entityName: parent.window.Xrm.Page.data.entity.getEntityName(), lineItems: [], customerName: result ? result.name : null, }; event.source.postMessage(JSON.stringify(entity), event.origin); } }); } response.id = id; response.data = data; response.entityName = entity.getEntityName(); response.accountnumber = entity.attributes .get("accountnumber") .getValue(); response.customerName = entity.attributes.get("name").getValue(); response.action = action; event.source.postMessage(JSON.stringify(response), event.origin); break; } return; };

e. Click Save and Publish.

  1. Add a new tab to Form (optional).

  2. To locate an external website, use the Component search field or navigate to Display > External website.

  3. Drag and drop the External website into the desired section.

  4. A popup will appear next to the External website. In this popup, enter the following URL:
    https://<customer cluster>.pricefx.com/pricefx/<partition>/saml/signon/<SAML configuration>/?RelayState=<relaystate>

     

  5. Modify fields in External Website:

    1. Label (optional)

    2. Name – Should be the same as in JavaScript code.

    3. Site URL – If URL was not added during Add external website, then it can be added now:
      https://<customer cluster>.pricefx.com/pricefx/<partition>/saml/signon/<SAML configuration>/?RelayState=<relaystate>

    4. Restrict cross frame scripting where supported – Should be unchecked.

       

  6. Click the Events tab in External website sidebar.

  7. To add a Pricefx event, click 'Event Handler.

  1. Add Library that you created in Step 8.

  2. Insert Function name that you created instead of PFXRegisterListener.

  3. Now click Save and Publish and verify if iFrame works.