Добро пожаловать в мой блог! Изначально он не задумывался как блог CRM разработчика, но жизнь сама внесла нужные коррективы. Тут я публикою все свои наблюдения относительно обозначенных в заголовке систем. Если Вы найдете в нем что-то интересное для Вас, как для заказчика, то буду рад сотрудничать с Вами! В моей компетенции 100% задач по MS CRM 3.0/4.0/2011:
MVP 2010, 2011
- Консалтинг
- Проектирование
- Разработка
- Обучение
MVP 2010, 2011
Полезный Popup. Часть 1. Упрощение создания Звонков.
Запись от Артем Enot Грунин размещена 29.03.2010 в 14:53
Теги fetch, java script, phonecall, popup
Доброго времени суток, коллеги. Не успел опубликовать данный пост до отпуска, хотя может быть оно и к лучшему, так как описанное в нем решение имеет ряд "дефектов", о которых позже...
Недавно на одном из проектов возникла задача: упростить ввод данных при создании действий типа Звонок: автоматически заполнять поле "Номер телефона" при выборе адресата. Задача, в общем-то, типовая, даже тривиальная. Сложность реализации заключалась лишь в визуальной части: заказчик просил отображать диалог выбора, на случай, если у Контакта, например, будет заполнено несколько полей с номерами телефонов – мобильный и рабочий. От реализации задачи удалось отбрехаться: мол, создавайте звонки из записи клиента, тогда, во-первых, отработает сопоставление атрибутов, а во-вторых, будет лишний повод просмотреть карточку и заполнить пару лишних полей.
Тем не менее, задача с визуальной частью показалась мне интересной, и я постарался реализовать подобное для саморазвития. В результате родился такой код:
Form OnLoad:
OnChange полей Отправитель и/или Получатель:
Результат работы кода можно увидеть на скриншоте ниже:
По клику на всплывающем окне соответствующий телефон вставляется в поле Номер телефона.
В ASPX я не силен, поэтому диалог выбора реализовывался как окно «попап». Возможно, такое решение даже более элегантно, так как не загромождает экран и упрощает развертывание. Данная реализация popup работает сугубо под IE, так что для CRM 5.0, которая, как мы надеемся, будет кросс-браузерной его придется переписать.
Все бы ничего, но я, каюсь, запамятовал, что поле «получатель» - PartyList, что обозначает, что получателей может быть несколько. Не знаю, как это выглядит с точки зрения логики, однако система позволяет выбирать сразу несколько получателей разного типа для одного звонка. На какое время я озадачился исправлением своего промаха, что и привело к задержке с публикацией, однако в процессе разработки мне посчастливилось найти иной подход к реализации задачи, о котором я расскажу в следующей части данной эпопеи.
В качестве отправной точки использовались следующие посты:
CRM Custom Tooltip
CRM Lookup Preview
Последний, кстати, и вдохновил на изменение концепции решения с целью сделать его универсальным. Продожение следует.
Недавно на одном из проектов возникла задача: упростить ввод данных при создании действий типа Звонок: автоматически заполнять поле "Номер телефона" при выборе адресата. Задача, в общем-то, типовая, даже тривиальная. Сложность реализации заключалась лишь в визуальной части: заказчик просил отображать диалог выбора, на случай, если у Контакта, например, будет заполнено несколько полей с номерами телефонов – мобильный и рабочий. От реализации задачи удалось отбрехаться: мол, создавайте звонки из записи клиента, тогда, во-первых, отработает сопоставление атрибутов, а во-вторых, будет лишний повод просмотреть карточку и заполнить пару лишних полей.
Тем не менее, задача с визуальной частью показалась мне интересной, и я постарался реализовать подобное для саморазвития. В результате родился такой код:
Form OnLoad:
Код:
var oTelField = crmForm.all.phonenumber; var oTelPopUp = new PhoneNumberPopUP(oTelField); function PhoneNumberPopUP(oField) { var This = this; This.EntityLookup = ""; This.Attributes = []; This.Labels = []; This.Icons = []; var oTelPopup = window.createPopup(); function reRenderControl() { oField.PhoneNumberPopUP = This; var oLabel = crmForm.all[oField.id + "_c"]; oLabel.style.textDecoration = "underline"; oLabel.style.color = "blue"; oLabel.attachEvent("onclick", This.showPopUP); oTelPopup.document.body.attachEvent("onclick", This.OnPopClick); } // Обработчик popup This.showPopUP = function() { var oPopUpHTML = This.getPopUpHTML(); oTelPopup.document.body.innerHTML = oPopUpHTML; var Width = oField.offsetWidth; // TODO: По длинне записи! //var Width = 180; var Height = This.Attributes.length * 22; var Position = This.getControlPostion(oField); var Left = Position.X + 1; var Top = Position.Y + 1; oTelPopup.show(Left, Top, Width, Height, null); } This.getPopUpHTML = function() { var oTelXML = This.fetchAttribData(); var oXmlDoc = new ActiveXObject("Microsoft.XMLDOM"); oXmlDoc.async = false; oXmlDoc.loadXML(oTelXML); var oPopUpHTML = "<table style='width:100%;height:100%;border:1px solid gray;font-family:Tahoma;font-size:11px'>"; for (var i = 0; i < This.Attributes.length; i++) { var telName = This.Attributes[i]; var telNode = oXmlDoc.selectSingleNode("/resultset/result/" + telName); var telNum = telNode != null ? telNode.text : ""; var telLabel = This.Labels[i]; var telIco = This.Icons[i] == 0 ? "ico_16_4210.gif" : "ico_18_4204.gif"; oPopUpHTML += "<tr style='cursor:pointer'>" + "<td><img src='/_imgs/" + telIco + "' /></td>" + "<td>" + telLabel + "</td>" + "<td>" + telNum + "</td>" + "</tr>"; } oPopUpHTML += "</table>"; return oPopUpHTML; } This.OnPopClick = function(event) { var phoneRow = event.srcElement; while (phoneRow.tagName != "TR") { phoneRow = phoneRow.parentElement; } var oTelNum = phoneRow.lastChild.innerText; oField.DataValue = oTelNum; } This.getControlPostion = function(control) { var Position = new Object(); var controlHeight = control.offsetHeight; var iY = 0, iX = 0; while( control != null ) { iY += control.offsetTop; iX += control.offsetLeft; control = control.offsetParent; } Position.X = iX + screenLeft; Position.Y = iY + screenTop + controlHeight; return Position; } This.fetchAttribData = function() { if (This.EntityLookup == null) return; var oFetchXML = "<fetch mapping='logical'>" + "<entity name='" + This.EntityLookup.typename + "'>"; for (var i = 0; i < This.Attributes.length; i++) { oFetchXML += "<attribute name='" + This.Attributes[i] + "'/>"; } oFetchXML += "<filter type='and'><condition attribute='" + This.EntityLookup.typename + "id' "; oFetchXML += "operator='eq' value='" + This.EntityLookup.id + "'/>"; oFetchXML += "</filter></entity></fetch>"; oFetchXML = oFetchXML.replace(/</g, '<'); oFetchXML = oFetchXML.replace(/>/g, '>'); var oSOAP = "<?xml version='1.0' encoding='utf-8'?>" + "<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'" + " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'" + " xmlns:xsd='http://www.w3.org/2001/XMLSchema'>" + GenerateAuthenticationHeader() + "<soap:Body>" + "<Fetch xmlns='http://schemas.microsoft.com/crm/2007/WebServices'>" + "<fetchXml>" + oFetchXML + "</fetchXml>" + "</Fetch>" + "</soap:Body>" + "</soap:Envelope>"; var oXmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); oXmlHttp.Open("POST", "/mscrmservices/2007/CrmService.asmx", false); oXmlHttp.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/crm/2007/WebServices/Fetch"); oXmlHttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8"); oXmlHttp.setRequestHeader("Content-Length", oSOAP.length); oXmlHttp.send(oSOAP); var oResponseText = oXmlHttp.responseXML.text; return oResponseText; } reRenderControl(); }
Код:
var oTelField = crmForm.all.phonenumber; var oTelPopUp = oTelField.PhoneNumberPopUP; var oEntityLookup = null; var oAttributes = []; var oLabels = []; var oIcons = []; if (event.srcElement.DataValue != null) { oEntityLookup = event.srcElement.DataValue[0]; var oTypeName = oEntityLookup.typename; switch (oTypeName) { case "account": { oAttributes = new Array("telephone1", "telephone2", "fax"); oLabels = new Array("Основной", "Дополнителельный", "Факс"); oIcons = new Array(0, 0, 1); break; } case "contact": { oAttributes = new Array("telephone1", "telephone2", "mobilephone", "fax"); oLabels = new Array("Основной", "Дополнителельный", "Мобильный", "Факс"); oIcons = new Array(0, 0, 0, 1); break; } case "lead": { oAttributes = new Array("telephone1", "telephone2", "fax"); oLabels = new Array("Основной", "Дополнителельный", "Мобильный", "Факс"); oIcons = new Array(0, 0, 0, 1); break; } case "systemuser": { oAttributes = new Array("address1_telephone1", "address1_telephone2", "mobilephone", "address1_fax"); oLabels = new Array("Основной", "Дополнителельный", "Мобильный", "Факс"); oIcons = new Array(0, 0, 0, 1); break; } } } oTelPopUp.EntityLookup = oEntityLookup; oTelPopUp.Attributes = oAttributes; oTelPopUp.Labels = oLabels; oTelPopUp.Icons = oIcons;
По клику на всплывающем окне соответствующий телефон вставляется в поле Номер телефона.
В ASPX я не силен, поэтому диалог выбора реализовывался как окно «попап». Возможно, такое решение даже более элегантно, так как не загромождает экран и упрощает развертывание. Данная реализация popup работает сугубо под IE, так что для CRM 5.0, которая, как мы надеемся, будет кросс-браузерной его придется переписать.
Все бы ничего, но я, каюсь, запамятовал, что поле «получатель» - PartyList, что обозначает, что получателей может быть несколько. Не знаю, как это выглядит с точки зрения логики, однако система позволяет выбирать сразу несколько получателей разного типа для одного звонка. На какое время я озадачился исправлением своего промаха, что и привело к задержке с публикацией, однако в процессе разработки мне посчастливилось найти иной подход к реализации задачи, о котором я расскажу в следующей части данной эпопеи.
В качестве отправной точки использовались следующие посты:
CRM Custom Tooltip
CRM Lookup Preview
Последний, кстати, и вдохновил на изменение концепции решения с целью сделать его универсальным. Продожение следует.
Всего комментариев 5
Комментарии
-
Добрый день. Подскажите пожалуйста как применить ваше решение чтобы окно с выбором телефонов поднималось по нажатию ISV-кнопки из грида и из формы. Не понятна именна та часть, которая кассаяется привязки попапа к полю Телефон:
var oTelField = crmForm.all.phonenumber;
var oTelPopUp = new PhoneNumberPopUP(oTelField);
function PhoneNumberPopUP(oField)
{
....
Что в моем случае надо передавать в функцию PhoneNumberPopUP?Запись от OlegaN размещена 30.04.2010 в 13:51 -
Запись от Артем Enot Грунин размещена 30.04.2010 в 13:56 -
Я хочу выполнять звонки из карточки/строки Контакта. Для этого планирую сделать ISV кнопку, которая будет получать все телефоы контакта и отображать их в попапе. А при выборе нужного телефона из попапа будет создаваться и открывться карточка Звонка со всеми нужными полями
Запись от OlegaN размещена 30.04.2010 в 14:04 -
Пишите с нуля - быстрее управитесь. Посмотрите последний пост про группировку в гриде. Там написано как сделать кнопку и привязать к ней меню. По нажатию я, очевидно, искал бы в гриде выбранную строку (строки?):
Код:var selected = crmGrid.innerGrid.selectedRecords[0];
Запись от Артем Enot Грунин размещена 30.04.2010 в 14:19 -
Здравствуйте!
Возможно оффтоп, но может Вы знаете: как на форму звонка подтащить данные из кастомного поля в карточке?Запись от lin2nil размещена 14.10.2011 в 16:47