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

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


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

Добавление связей из формы объекта

Запись от Артем Enot Грунин размещена 04.11.2009 в 16:24

В CRM 3.0 в свое время был исправлен один интересный "баг": если на форме организации заполнить поле "основной контакт", то этот контакт не появится в списке контактов от организации. Почему я написал баг в ковычках? А это и не баг вовсе, а вполне логичное поведение системы. Разные связи между объектами - разные списки и контролы. В этом смысле основному контакту вообще не обязательно быть связанным с самой организацией. Мнение заказчика, тем не менее, может существенно отличаться от моего. Выход - при заполнении лукапов добавлять соответствующую связь между объектами. Адепты поддерживаемых методов, коим я сам когда-то был, даже скажут вам как: нужно писать плагин на PostSave. Иногда, впрочем, результат нужно отразить немедленно и остается стучаться в веб сервисы CRM через Java Script. Все мы помним как страшно выглядит этот фаршированный XML'ем код в жалком окне обработчика... И вот тут глаз падает на кнопочку "Добавить существующий" на панели связанного объекта... Все верно - там проще!
По нажатии на эту кнопку вызывается либо функция
Код:
locAssocOneToMany(iType, sRelationshipName);
либо
Код:
locAssocObj(iType , sSubType, sAssociationName, iRoleOrdinal)
в зависимости от типа связи. Обе функции расположены в файле CRMWeb\_static\_grid\action.js. Они вызывают лукап выбора и передают выбранные значения в дальнейшую обработку. В случае когда связь 1:N логику ф-ции придется повторить, а вот для N:N вполне можно написать универсальный гибкий код. Что я и сделал в приложении для примера из своего поста Укрощение Advanced Find, часть 2 - написал функцию, которая связывает найденные в поиске продукты с оригинальным Интересом. Подход имеет неожиданный подводный камень: попытка заново связать уже связанные объекты приводит к ошибке ядра, после чего на форму вылетит пугающее не информативное окно. Иными словами, перед связыванием объектов необходимо убедиться в уникальности создаваемой связи.
Код:
var oTypeThis = crmForm.ObjectTypeCode;
var oTypeThisName = crmForm.ObjectTypeName;
var oTypeAssociated = Product;
var oTypeAssociatedName = "product";
var oAssociationName = "new_productsForLead";
var oAssociationRecordName = "new_productsforlead";

function initAction()
{
    if (oFrameAF.readyState != "complete")
    {
        onError(oErrorFrameNotReady);
        return;
    }

    var oDoc = oFrameAF.contentWindow.document;
    var oResultFrame = oDoc.getElementById("resultFrame");
    var oGridFrameDoc = oResultFrame.contentWindow.document;
    var oGrid = oGridFrameDoc.getElementById("crmGrid");

    // Дочерний фрейм всегда готов, но не факт что что-то содержит!
    if (oGrid == null)
    {
        onAlert(oErrorResultsNotReady);
        return;
    }

    var oSelectedRecords = oGrid.InnerGrid.SelectedRecords;

    if (oSelectedRecords == null || oSelectedRecords.length == 0)
    {
        onAlert(oErrorNoSelected);
        return;        
    }

    var oAssociatedRecords = getAssociatedRecordsIds();
    var oNewItemsIds = getMegredItems(oAssociatedRecords, oSelectedRecords);

    AssociateObjects(crmForm.ObjectTypeCode, crmForm.ObjectId, oTypeAssociated, oNewItemsIds, false, "", oAssociationName);

    var addedCount = oNewItemsIds.items.length;
    var skippedCount = oSelectedRecords.length - addedCount;
    onAlert("Добавлено записей: " + addedCount + ". Пропущено записей: " + skippedCount);
}

function getAssociatedRecordsIds()
{
    var oFetchXML =    "<fetch mapping='logical'>" +
                "<entity name='" + oAssociationRecordName + "'>" +
                    "<attribute name='" + oTypeAssociatedName + "id'/>" +
                    "<filter type='and'>" +
                        "<condition attribute='" + oTypeThisName + "id' operator='eq' value='" + crmForm.ObjectId + "'/>" +
                    "</filter>" +
                "</entity>" +
            "</fetch>";

        oFetchXML = oFetchXML.replace(/</g, '&lt;');
        oFetchXML = oFetchXML.replace(/>/g, '&gt;');

    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;

    var oXmlDoc = new ActiveXObject("Microsoft.XMLDOM");
    oXmlDoc.async = false; 
    oXmlDoc.loadXML(oResponseText);

    var results = oXmlDoc.getElementsByTagName(oTypeAssociatedName + "id");
    var associatedRecordsIds = new Array(results.length);

    for (var i = 0; i < results.length; i++)
    {
        associatedRecordsIds[i] = results[i].text;
    }
    return associatedRecordsIds;
}

function getMegredItems(oAssociatedRecords, oSelectedRecords)
{
    var oMergedIds = new LookupArgsClass();
    var oItems = new Array();
    
    for (var i=0; i < oSelectedRecords.length; i++)
    {
        var doExist = false;
        var oCandidate = oSelectedRecords[i][0];

        for (var j=0; j < oAssociatedRecords.length; j++)
        {
            if (oAssociatedRecords[j] == oCandidate)
            {
                doExist = true;
                break;
            }
        }

        if (doExist == false)
        {
            oItems.push(new Item(oSelectedRecords[i][0]))
        }
    }
    oMergedIds.items = oItems;
    return oMergedIds;
}

function onAlert(oMessage, oType)
{
    alert(oMessage);
}


function Item(oId)
{
    this.id = oId;
}
Думаю, вам не составит труда адаптировать код под свои нужды.
Размещено в CRM
Просмотров 23669 Комментарии 0
Всего комментариев 0

Комментарии

 


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