Кастомизация
24
Авг
10

Количество не просмотренных действий

Если Вы когда-нибудь работали с Outlook’ом (да и с многими другими email-клиентами), то значете, что при получении нового письма, папка, в которую оно попадает, выделяется полужирным начертанием, а справа от ее названия появляется количество новых писем, попавших в нее. Весьма удобный функционал – экономит кучу времени – не нужно постоянно просматривать все папки на наличие новых писем, а достаточно взглянуть на заголовок, чтобы понят есть ли они 🙂 Вообщем, реализуем нечто подобное в CRM 🙂

Логика работы такова:

  • Зписиями, требущими подсчета, будем считать те, которые назначены на текущего пользователя (т.е. он является ихнем владельцем);
  • Объекты, кторые будем считать:
    • Задача;
    • Электронная почта;
    • Факс;
    • Письмо;
    • Встреча;
    • Звонок.
  • Критерием новизны записи считается «флаг» (обычное битовое поле который мы создадим далее);
  • При открытии карточки выше указанных объектов, будем обновлять статус флага на «просмотрено»;
  • Обновление количества не просмотренных действий будет происходит с определенным интервалом, в случае наличия пункта меню Действия в текущем окне.

Приступим:

  • Для начала нам понадобится «флаг» на форме объектов, которые мы будем отслеживать на «новизну». Поэтому для объектов, которые будем просматривать, создайте новый атрибу с именем visited, типом bit и дефолтным значение «Нет». И вынесите его на форму этих объектов.


Далее…

  • Откройте файл <сайт CRM>\_root\navbarpage.aspx в каком-нибудь текстовом редакторе;
  • Добавьте в конце такие строчки кода:
    <script type="text/jscript">
        // Запускаем функцию подсчета не просмотренных действий
        setTimeout(updActiv, 1000);
    
        // Функцию подсчитываем не просмотренные действия
        function updActiv() {
            // Ищем в навигационном мену пункт Действия
            a = document.getElementById('nav_activities');
            // Если он существует...
            if (a) {
                // Задаем имена объектов, в которых будем считать не просмотренные записи
                var array = ['task', 'email', 'fax', 'letter', 'appointment', 'phonecall'];
                // Изначально количество равно 0
                totalActiv = 0;
                // Поочередно подсчитываем количество не просмортенных действий по объектам и суммируем их
                for (var key in array) {
                    totalActiv += eval(fetch(array[key]));
                }
                // Обновляем надпись
                a.childNodes[1].innerText = "Действия" + " (" + totalActiv + ")";
            }
            
            // Ждем 3 минуты и повторяем процедуру
            setTimeout(updActiv, 180000);
        }
    
        // Функция отправляющая Fetch-запрос в CRM для подсчета количества не просмортенных действий по одному объекту
        function fetch(entity) {
            var authenticationHeader = GenerateAuthenticationHeader();
            var xml = "<?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'>" +
            authenticationHeader +
            "<soap:Body>" +
            "<Fetch xmlns='http://schemas.microsoft.com/crm/2007/WebServices'>" +
            "<fetchXml>" +
            "&lt;fetch mapping='logical' aggregate='true' &gt;" +
                "&lt;entity name='" + entity + "'&gt;" +
                    "&lt;attribute name='new_visited' aggregate='count' alias='visited' /&gt;" +
                    "&lt;filter>" +
                        "&lt;condition attribute='new_visited' operator='eq' value='0' /&gt;" +
                        "&lt;condition attribute='ownerid' operator='eq-userid' /&gt;" +
                    "&lt;/filter&gt;" +
                "&lt;/entity&gt;" +
            "&lt;/fetch&gt;" +
            "</fetchXml>" +
            "</Fetch>" +
            "</soap:Body>" +
            "</soap:Envelope>";
            var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
            xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
            xHReq.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/crm/2007/WebServices/Fetch");
            xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
            xHReq.setRequestHeader("Content-Length", xml.length);
            xHReq.send(xml);
            var resultXml = xHReq.responseXML;
    
            var errorCount = resultXml.selectNodes('//error').length;
            if (errorCount != 0) {
                var msg = resultXml.selectSingleNode('//description').nodeTypedValue;
                alert(msg);
            } else {
                var resultSet = new String();
                resultSet = resultXml.text;
                var oXmlDoc = new ActiveXObject("Microsoft.XMLDOM");
                oXmlDoc.async = false;
                oXmlDoc.loadXML(resultSet);
                var results = oXmlDoc.getElementsByTagName('result');
                var msg = results[0].selectSingleNode('./visited').nodeTypedValue;
                return msg;
            }
        }
    </script>
    

    Этот код делает следующее:

    • Обявляет функцию updActiv, которая проверяет пункт наличие пункта меню Действия и в случае положительного результата…
    • Начинает перебор объектов входящих в группу действий (и перечисленных в массиве array) и составляет с помощью функции fetch запрос в CRM для подсчета их количества по каждому объекту для текущего пользователя с флагим равным единице;
    • Затем добавляем к пункту меню Действия количество найденных не просмотенных записей;
    • Ну, и в конце функция updActiv включается таймаут на 3 минуты, по истечении которого функция перезапускает сама себя 🙂


  • Повесьте на онлоад форм всех выше указанных объектов такой код:
    // Скрываем "флаг"
    crmForm.all.new_visited_c.style.display = 'none';
    crmForm.all.new_visited_d.style.display = 'none';
    
    // Если флаг не равен единице и это не форма Создания записи
    if (crmForm.all.new_visited.DataValue != 1 && crmForm.ObjectId) {
        // То обновляем для ее флаг на единицу (SOAP-запросом)
        var authenticationHeader = GenerateAuthenticationHeader();
    
        var xml = "<?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'>" +
        authenticationHeader +
        "<soap:Body>" +
        "<Update xmlns='http://schemas.microsoft.com/crm/2007/WebServices'>" +
        "<entity xsi:type='email'>" +
        "<new_visited>1</new_visited>" +
        "<emailid>" + crmForm.ObjectId + "</emailid>" +
        "</entity>" +
        "</Update>" +
        "</soap:Body>" +
        "</soap:Envelope>";
    
        var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
        xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
        xHReq.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/crm/2007/WebServices/Update");
        xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
        xHReq.setRequestHeader("Content-Length", xml.length);
        xHReq.send(xml);
        var resultXml = xHReq.responseXML;
    
        var errorCount = resultXml.selectNodes('//error').length;
        if (errorCount != 0) {
            var msg = resultXml.selectSingleNode('//description').nodeTypedValue;
            alert(msg);
        }
    }
    

    Этот код просто скрывает флаг и обновляет его если он не равен единице (а также при наличии GUID’а у текущей записи). Также учтите, что тут захардкоден объект email – поэтому при размещении на других объектах подправьте его.


Вроде все… перейдите в навигационном меню, где есть пункт Действия и смотрите как JS подсчитает количество не просмотренных записей.


З.Ы. Здесь представлен весьма упращенный функционал, который не учитвыает поведение флага при создании и переназначение записей действий. Но это уже зависит от конкретной ситуации и возлагается на Ваши плечи 🙂

Комментарии (10)
  • mc707 24.08.2010

    Добрый день!

    При открытии любого из действий срабатывает функция OnLoad и вылезает ошибка » ‘Email’ entity doesnt contain attribute with Name = ’emailid’ «.
    Соответственно вопрос — почему сущность везде ’email’ и почему не найден атрибут emailid. Пробовал удалить всю строчку с emailid — пишет ‘unexpected error’.

  • slivka_83 24.08.2010

    Доброе время суток! 🙂

    Сущность не везде email 🙂

    > Также учтите, что тут захардкоден объект email – поэтому при размещении на других объектах подправьте его!

  • Алексей 24.08.2010

    Скажите, пожалуйста, в соап-запросе с агрегацией, помимо count можно ли использовать другие функции, типа min max, дело в том, что здесь http://community.dynamics.com/product/crm/f/117/p/6918/11320.aspx написано, что нельзя…

  • slivka_83 24.08.2010

    Все верно 🙂 только count: http://msdn.microsoft.com/en-us/library/dd904030.aspx

  • Алексей 24.08.2010

    Ага, спасибо!
    Уже сам протестил ))

    Они, кстати, пишут, что в новой версии CRM тоже не факт, что нормальная агрегация появится…

  • Иван 24.08.2010

    Подскажите, у меня при создании новой формы и назначении на другого пользователя показывает действительно что ему пришло новое действие, а вот он его открыл посмотрел и закрыл, а все равно это действие висит как новое. Где копать??

  • Иван 24.08.2010

    Вернее, визитед не становиться после открытия формы в 1.

  • slivka_83 24.08.2010

    И никаких ошибок при этом не выводится?

  • Иван 24.08.2010

    Неа. Ошибок нет, просто реквизит визитетед после открытия формы не меняет своего значения.

  • slivka_83 24.08.2010

    Ну, тогда нада как-то отлаживать… что-то типа http://mmcrm.ru/?p=475

*

code