28.08.2013, 15:11 | #1 |
Участник
|
axforum blogs: Как создать звонок или встречу для кастомного объекта
Источник: http://axforum.info/forums/blog.php?b=421
============== В одном из своих прошлых постов, я писал про сходства и отличия стандартных и кастомных типов действий: CRM 2011 Custom Activitys - Особенонсти. Тогда я коснулся только верхнеуровневых объектов действий, но не затрагивал такой интересный "подобъект" как "Стороны действия" (activity party). Что такое стороны действия, вы можете подробно почитать в SDK. Если кратко, все действия (кроме задачи) связывают несколько сторон, или участников. Например, действие «Электронная почта» имеет «Получателей» и «Отправителя», встреча имеет «Участников» и «Организатора», и т.д. Все разновидности участников называются Сторонами действия. Кроме того, стороны привязываются к особым системным типам полей множественного выбора "PartyList". Это и есть те самые поля "Получатель" (почта), "Обязательные участники" (встреча) и пр. Впрочем, оставим этот ликбез и перейдем, собственно, к задаче. Недавно мой хороший знакомый и недавний коллега по MS Андрей Слепицкий обратился ко мне с вопросом: можно ли использовать кастомные объекты как стороны действия? Например, мы ввели в систему отдельную сущность Партнер и хотим позвать партнера на встречу. Сперва задача показалась мне простой: в чем проблема - разрешить действия в настройках объекта?: Однако, все оказалось сложнее. К сожалению, система позволяет выбор кастомного объекта только в поле "В отношении", но не в других полях, таких как "Обязательные участники" встречи. Небольшое исключение составляет форма Электронной почты. Если отметить вторую галочку: Sending e-mail, система позволит выбирать кастомный объект в поле "Получатель" (to) на форме электронной почты. Но как же быть с остальными полями? Для того чтобы исследовать феномен, я решил провести зловещий эксперимент. Для этого я модифицировал пример создания встречи из SDK Sample: Book an Appointment чтобы добавить в список участников встречи свой кастомный объект: X++: String crmconnection = "Server=http://crm/FixRM"; CrmConnection connection = CrmConnection.Parse(crmconnection); OrganizationService service = new OrganizationService(connection); WhoAmIRequest userRequest = new WhoAmIRequest(); WhoAmIResponse userResponse = (WhoAmIResponse) service.Execute(userRequest); // Create the ActivityParty instance. ActivityParty me = new ActivityParty { PartyId = new EntityReference(SystemUser.EntityLogicalName, userResponse.UserId) }; ActivityParty customparty= new ActivityParty { // PartyId = new EntityReference("fixrm_customparty", new Guid("6793AD07-E70E-E311-8E30-080027004A52")) }; // Create the appointment instance. Appointment appointment = new Appointment { Subject = "Test Appointment", Description = "Test Appointment created using the BookRequest Message.", ScheduledStart = DateTime.Now.AddHours(1), ScheduledEnd = DateTime.Now.AddHours(2), Location = "Office", RequiredAttendees = new ActivityParty[] { me, customparty}, Organizer = new ActivityParty[] { me } }; // Use the Book request message. Guid id = service.Create(appointment); p.s. Для простоты тут я использую метод Create а не Book. Результат эксперимента показал следующее:
Иными словами, использовать кастомные объекты в действиях можно, единственная проблема - это как-то добавить эту возможность в пользовательский интерфейс. И вот тут начинается небольшой, но грязный unsupport… Ниже к посту приложено неуправляемое решение, которое реализует искомую функциональность. Трюк заключается в том чтобы средствами JS DOM изменить атрибуты lookuptypes, lookuptypeIcons и lookuptypenames у нужного lookup контрола при загрузке формы. Как это часто бывает с ансаппортом, непонятно на что влияет последний атрибут - все работает и без него, однако его я для порядка тоже привожу в соответствие. X++: if (typeof (FixRM) == "undefined") { FixRM = { __namespace: true }; } /* Events FixRM.CustomActivityParty.AddPartyTypeOnLoad */ FixRM.CustomActivityParty = { AddPartyTypeOnLoad: function (settings) { for (var setting in settings) { var parties = settings[setting]; for (var i = 0; i < parties.length; i++) { var party = parties[i]; this.AddPartyType(setting, party.otc, party.schema, party.schemaName); if (party.isDefault == true) { this.SetDefaultParty(setting, party.otc, party.DefaultViewId); } } } }, AddPartyType: function (name, otc, schema, schemaName) { function ApendAttributeValue(node, name, separator, value) { var attribute = node.getAttribute(name); var attributeValues = attribute.split(separator); attributeValues.push(value); attribute = attributeValues.join(separator); node.setAttribute(name, attribute); } var lookup = document.getElementById(name); if (lookup && lookup.attributes) { ApendAttributeValue(lookup, "lookuptypes", ",", otc); var icoPath = Xrm.Page.context.prependOrgName("/_Common/icon.aspx?cache=1&iconType=GridIcon&objectTypeCode=" + otc); ApendAttributeValue(lookup, "lookuptypeIcons", ":", icoPath); if (schema && schemaName) { var lookuptypename = schema + ":" + otc + ":" + schemaName; ApendAttributeValue(lookup, "lookuptypenames", ",", lookuptypename); } } }, SetDefaultParty: function (name, otc, view) { var lookup = document.getElementById(name); if (lookup && lookup.attributes) { lookup.setAttribute("defaulttype", otc); if (view) { lookup.setAttribute("defaultViewId", view); } } }, __namespace: true }; Второй неприятный момент заключается в том, что данный функционал активно использует числовой ObjectTypeCode, который, вообще-то deprecated и в следующих версиях должен быть полностью заменен на строковое свойство LogicalName. Исходя из этого, опасно кодировать подобную функциональность непосредственно в тексте программы. Для того чтобы облегчить переносимость, реализация принимает параметры из настроек обработчика события формы: Настройки задаются как строка JSON: X++: { имя поля1: [ массив добавляемых типов участников ], имя поля2: [ массив добавляемых типов участников ] } Сами типы участники задаются в формате: X++: { oct: , schema: , schemaName: , isDefault: , DefaultViewId: } Приятно удивил тот факт, что система автоматически приводит текст JSON параметра к JS объекту, поэтому нет необходимости парсить его самостоятельно. Заключение Ни я ни Андрей не смогли выяснить, является ли это решение поддерживаемым хотя бы частично. Визуальная часть - не поддерживается абсолютно! Остается вопрос, можно ли делать такие вещи через вызовы SDK. На мой взгляд это ограничение - не более чем недосмотр разработчиков. Время покажет! Вложения FixRMCustomActivityParty_1_0_0_0.zip (21.0 Кб, 0 просмотров) Источник: http://axforum.info/forums/blog.php?b=421
__________________
Расскажите о новых и интересных блогах по Microsoft Dynamics, напишите личное сообщение администратору. |
|
28.08.2013, 19:31 | #2 |
Moderator
|
Да, по визуальной части (а это все-таки основной сценарий работы) кастомизация неподдерживаема. Более того, как говорится "changing the lookuptypenames via JS is known to cause memory management issues in client machines", соответственно, даже, если хочется, все равно так делать не надо
|
|
|
Опции темы | Поиск в этой теме |
Опции просмотра | |
|