Добро пожаловать в мой блог! Изначально он не задумывался как блог 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
-
Пишите с нуля - быстрее управитесь. Посмотрите последний пост про группировку в гриде. Там написано как сделать кнопку и привязать к ней меню. По нажатию я, очевидно, искал бы в гриде выбранную строку (строки?):
Вычитывал id объекта и далее все как в примере... Как открывать карточку с заранее заполненными полями можете почитать в одном из моих первых постов.Код:var selected = crmGrid.innerGrid.selectedRecords[0];
Запись от Артем Enot Грунин размещена 30.04.2010 в 14:19
-
Здравствуйте!
Возможно оффтоп, но может Вы знаете: как на форму звонка подтащить данные из кастомного поля в карточке?Запись от lin2nil размещена 14.10.2011 в 16:47



