AXForum  
Вернуться   AXForum > Блоги > CRM, SharePoint и Черная Магия
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

Добро пожаловать в мой блог! Изначально он не задумывался как блог CRM разработчика, но жизнь сама внесла нужные коррективы. Тут я публикою все свои наблюдения относительно обозначенных в заголовке систем. Если Вы найдете в нем что-то интересное для Вас, как для заказчика, то буду рад сотрудничать с Вами! В моей компетенции 100% задач по MS CRM 3.0/4.0/2011:
  • Консалтинг
  • Проектирование
  • Разработка
  • Обучение


MVP 2010, 2011
Оценить эту запись

Укрощение Advanced Find, часть 2

Запись от Артем Enot Грунин размещена 22.10.2009 в 19:53
Обновил(-а) Артем Enot Грунин 03.11.2009 в 15:49

В своем прошлом посте я рассматривал довольно типовую задачу быстрого поиска записей средствами Advanced Find, на основе очередной инкарнации известного всем "IFrame Fetch Viewer". Напомню, что задача в моем примере стояла не показать некую выборку в виде стандартной таблицы с результатами, а помочь менеджеру быстро приступить к поиску нужных вариантов. Иными словами, мне было нужно не столько показать результат, сколько настроить фильтр и показать его пользователю. Рассмотрим на примере: клиент приходит к менеджеру заказчика и говорит: "мне нужен красный шкаф таких-то размеров". Менеджер открывает новый Интерес и заполняет параметры заявки: размеры и цвет шкафа. Далее ему нужно открыть диалог расширенного поиска, выбрать поиск по Продуктам, далее забить фильтр с параметрами. Пусть мы имеем дело с прожженным пользователем CRM и подходящий фильтр у него уже заготовлен, но что если категорий продукта несколько десятков? Пусть теперь не найдется продукта полностью удовлетворяющего заказчика, тогда менеджеру придется поиграть с параметрами запроса, чтобы найти нечто отдаленно напоминающее то что хотел клиент. В случае успеха менеджер скажет: "Вы знаете, красный - это так пошло! Возмите-ка синий!". Клиент согласится подумать и придет отнимать время менеджера завтра и история повторится. Вот тут мы и приходим к понимаю того, что иногда на основании входных параметров удобно формировать сам фильтр, а не готовую выборку. Как это сделать?
Пройдем по шагам:
1. Кастомизируем сущность Продукт.
Добавим два атрибута типа decimal: new_width и new_height и один picklist new_color c опциями 'Red', 'Green', 'Blue'. Разместим все новые атрибуты на форме.

2. Создадим и сохраним запрос для поиска продуктов с ограничениями по этим полям. Нужен любой осмысленный запрос, нам потребуется только его прямой url и его FetchXML.

3. Кастомизируем сущность Интерес.
Добавим к ней все те же атрибуты что и к продукту, а так же разместим на ее форме фрейм IFrame_af, свойство src которого должно указывать на url нашего сохраненного запроса.

4. На событие OnLoad интереса вешаем следующий код:
Код:
var oFrame = crmForm.all.IFRAME_af;
prepareAFFrame(oFrame);

function prepareAFFrame(oFrame)
{
    // Ставим мультик на загрузку фрейма
    var oLoadingTitle = "We roll'n roll'n roll'n!";
    var odoc = oFrame.contentWindow.document;
    odoc.body.innerHTML = "<table height='100%' width='100%' style='cursor:wait'>" +
                    "<tr>" +
                        "<td valign='middle' align='center'>" +
                            "<img alt='' src='/_imgs/AdvFind/progress.gif'/>" +
                            "<br>" + oLoadingTitle + 
                        "</td>" +
                    "</tr>" +
                "</table>";

    // Инициализируем фрейм когда он прогрузится
    oFrame.attachEvent('onreadystatechange', function()
    {
        if (oFrame.readyState != 'complete') return;

        var odoc = oFrame.contentWindow.document;

        // Причесываем
        odoc.getElementById("crmMenuBar").style.display = "none";

        var oCols = odoc.getElementsByTagName("COLGROUP")[0];
        oCols.childNodes[0].style.display = "none";
        oCols.childNodes[2].style.display = "none";


        // Возможно мы захотим блокировать поиск других объектов
        //odoc.getElementById("slctPrimaryEntity").disabled = true;

        // Вся логика помещана в один из обработчиков
        window.setTimeout("crmForm.all.new_color.FireOnChange()",100);
    });
}
Этот код выполняет подготовку нашего фрейма к использованию: скрывает лишние элементы окна, показывает мультик пока фрейм загружается и заполняет поисковый фильтр сохраненными значениями с формы. К сожалению, CRM 4.0 позволяет нам размещать свой код только в обработчиках событий, поэтому мы разместим функцию обновления фильтра в одном из них:

5. В событии OnChange поля new_color:
Код:
var oFrame = crmForm.all.IFRAME_af;
RefreshFrame(oFrame);

function RefreshFrame(oFrame)
{
     if (oFrame != null && oFrame.contentWindow.document.readyState == "complete")
    {
      // получаем фильтр
      var oFetchXml = getFetchXML();

      //var oFrame = crmForm.all.IFRAME_af;
      var odoc = oFrame.contentWindow.document;
      var oAf = odoc.getElementById("advFind");

      oAf.Clear(true); // иногда валится если фрейм не успел загрузиться!
      oAf.FetchXml = oFetchXml;
      oAf.IsDirty = false; // Сбрасываем флаг изменений
    }
}

function getFetchXML()
{
    var oFetchXml = '<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">'
                + '<entity name="product"><attribute name="name"/>'
                +    '<attribute name="productid"/>'
                +    '<attribute name="new_width"/>'
                +    '<attribute name="new_height"/>'
                +    '<attribute name="new_color"/>'
                +    '<order attribute="name" descending="false"/>'
                +        '<filter type="and">'
+    (crmForm.all("new_color").DataValue != null?    '<condition attribute="new_color" operator="eq" value="{0}"/>' : "")
+    (crmForm.all("new_height").DataValue != null?    '<condition attribute="new_height" operator="ge" value="{1}"/>' : "")
+    (crmForm.all("new_width").DataValue != null?    '<condition attribute="new_width" operator="ge" value="{2}"/>' : "")
                +        '</filter>'
            +    '</entity>'
            +'</fetch>';

    // Поле 0
    oFetchXml = oFetchXml.replace("{0}", crmForm.all("new_color").DataValue);
    // Поле 1
    oFetchXml = oFetchXml.replace("{1}", crmForm.all("new_height").DataValue);
    // Поле 2
    oFetchXml = oFetchXml.replace("{2}", crmForm.all("new_width").DataValue);
    // * * *

    return oFetchXml;
}
Функция RefreshFrame убеждается что фрейм готов к работе (он может находиться на разных вкладках с полями заявки и не быть инициализированным) после чего собирает стоку FetchXml фильтра и обновлет фрейм. Для удобства внесения изменений, код формирования запроса вынесен в отдельную функцию. Обратите внимание, что поля на форме могут не содержать значений. В этом случае требуется удалять соответствующие условия из фильтра, иначе Advanced Find будет требовать заполнить все пустые поля запроса.

6. В обработчик OnChange всех прочих полей заявки (new_height и new_width) следует поместить код:
Код:
crmForm.all.new_color.FireOnChange()
Он только перевызывает описанные выше функции.

7. Если пользователь менял фильтр руками, форма будет запрашивать сохранение изменений. Чтобы этого избежать, на OnSave формы поместите код:
Код:
var oFrame = crmForm.all.IFRAME_af;
DropFilterChanges(oFrame);

function DropFilterChanges(oFrame)
{
      var odoc = oFrame.contentWindow.document;
      var oAf = odoc.getElementById("advFind");
      oAf.IsDirty = false; // Сбрасываем флаг изменений
}
8. Публикуем изменения. Можно пользоваться.



Решение можно дополнить, создав связь многие ко многим между сущностями Продукт и Интерес для хранения "Предложенных вариантов". Тогда, например, по нажатию кастомной кнопки на тулбаре можно будет добавлять найденные продукты в список предложенных клиенту вариантов, чтобы их не приходилось искать повторно.

Изменение от 03.11.09: Реализацию смотрите в посте: Добавление связей из формы объекта.

p.s. Огромное спасибо Андрею a33ik Бутенко, за неоценимую помощь в отладке этого кода. Не будь тебя, друг, JS меня бы одолел!
Миниатюры
Нажмите на изображение для увеличения
Название: af.jpg
Просмотров: 820
Размер:	81.7 Кб
ID:	17  
Размещено в CRM
Просмотров 167854 Комментарии 9
Всего комментариев 9

Комментарии

  1. Старый комментарий
    Аватар для a33ik
    Да ладно =) Я так - плюшками балуюсь =)
    Запись от a33ik размещена 22.10.2009 в 20:05 a33ik is offline
  2. Старый комментарий
    Аватар для Артем Enot Грунин
    Цитата:
    Сообщение от a33ik Просмотреть комментарий
    Да ладно =) Я так - плюшками балуюсь =)
    Хоть за камент спасибо. Посмотрел хоть как они выглядят.
    Запись от Артем Enot Грунин размещена 22.10.2009 в 21:53 Артем Enot Грунин is offline
  3. Старый комментарий
    Аватар для Gustav
    Артем, всё у Вас здОрово. Народ просто не решается красоту "ночного города" комментами разбавлять Кстати, фон не слишком темноват ли всё-таки?
    Запись от Gustav размещена 23.10.2009 в 10:55 Gustav is offline
  4. Старый комментарий
    Аватар для Артем Enot Грунин
    Цитата:
    Сообщение от Gustav Просмотреть комментарий
    Артем, всё у Вас здОрово. Народ просто не решается красоту "ночного города" комментами разбавлять Кстати, фон не слишком темноват ли всё-таки?
    Я, помнится, пол ночи со стилями оформления боролся. Не знаю решусь ли на это вотрой раз.
    Запись от Артем Enot Грунин размещена 23.10.2009 в 11:01 Артем Enot Грунин is offline
  5. Старый комментарий
    Аватар для Lemming
    Цитата:
    Сообщение от Артем Enot Грунин Просмотреть комментарий
    Я, помнится, пол ночи со стилями оформления боролся.
    А не подскажите куда ткнуть, что бы увидеть настройки стилей, а то что-то я в упор не вижу ?
    Запись от Lemming размещена 27.10.2009 в 16:45 Lemming is offline
  6. Старый комментарий
    Аватар для Артем Enot Грунин
    Цитата:
    Сообщение от Lemming Просмотреть комментарий
    А не подскажите куда ткнуть, что бы увидеть настройки стилей, а то что-то я в упор не вижу ?
    Блок "опции" последняя строка "Управление блогом" далее "Изменение стиля блога". Как-то так.
    Запись от Артем Enot Грунин размещена 27.10.2009 в 16:49 Артем Enot Грунин is offline
  7. Старый комментарий
    Аватар для Lemming
    Цитата:
    Сообщение от Артем Enot Грунин Просмотреть комментарий
    Блок "опции" последняя строка "Управление блогом" далее "Изменение стиля блога". Как-то так.
    Хмм...вот как у меня выглядит управление блогами:



    Может это доступно только модераторам или вообще отключили эту опцию, если там есть доступ к чистому html, который не проходит через фильтры?
    Запись от Lemming размещена 27.10.2009 в 17:04 Lemming is offline
  8. Старый комментарий
    Аватар для Артем Enot Грунин
    Цитата:
    Сообщение от Lemming Просмотреть комментарий
    Хмм...вот как у меня выглядит управление блогами:



    Может это доступно только модераторам или вообще отключили эту опцию, если там есть доступ к чистому html, который не проходит через фильтры?
    Блин, атачи нельзя в каменты делать... У меня сразу под "Ваш блог" есть нужный пункт. Вам, наверно, к Mazzy тогда стоит обратиться.
    Запись от Артем Enot Грунин размещена 27.10.2009 в 17:14 Артем Enot Грунин is offline
  9. Старый комментарий
    Аватар для Lemming
    Цитата:
    Сообщение от Артем Enot Грунин Просмотреть комментарий
    Блин, атачи нельзя в каменты делать... У меня сразу под "Ваш блог" есть нужный пункт. Вам, наверно, к Mazzy тогда стоит обратиться.
    Ок, спасибо, попробую обратиться к нему.
    Запись от Lemming размещена 27.10.2009 в 17:19 Lemming is offline
 


Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 20:53.