Добрый день. BPM 7.10.1
Подскажите какое событие отрабатывает после полной отрисовки карточки.
Ситуация такая: есть карточка контакта, на ней tabPanel. так вот при срабатывании onRender по сути карточка ещё не отрисовалась, на вкладке ещё нет элементов... Какое событие отрабатывает после полной прорисовки карточки?

Нравится

2 комментария

На текущий момент такого метода у нас нет, табы отрисовываются асинхронно. Но вы можете воспользоватся событиями отрисовки дом элементов которые вас интересуют:
https://toster.ru/q/210143

Загрузку чего вам конкретно надо дождаться ?
Зачастую проблемы связаны с ActionDashboard, метод карточки onEntityInitialized отрабатывает до его окончательной загрузки, но у этой проблемы есть решение.
Необходимо будет заместить схему SeactionActionDashboard где проконтролировать установку значения атрибута IsDashboardItemsLoading
PS: пишите в лс, если надо могу прям код замещающей схемы целиком выдать.

Показать все комментарии

Всем доброго времени суток.
Хотелось бы узнать если ли возможность в элемент бизнес-процесса "Задание-сценарий" вставить запрос к базе данных и если есть, то можно хоть самый простой пример c Select.

Нравится

2 комментария

Вопрос прост, т.к. иногда this.callParent это вызов с асинхронной логикой, то хотелось бы иметь callback для такого вызова ?
Вопрос - существуют ли для этого штатные средства, или надо что-то придумывать ?
А может кто-то уже что-то придумал :)

Нравится

4 комментария

Здравствуйте, Илья!

А можно пример бизнес задачи, которую нужно решить используя callback после вызова callParent.

У кейса который я описываю - есть альтернативное решение, но как пример подойдет:
схема SectionActionDashboard метод init
по факту после завершения цепочки вызовов initв схемах наследования
SectionActionDashboard окончательно готов к работе, отрисован и наполнен данными.
Есть необходимость получать уведомление о таком факте, так как в интерфейсе SectionActionDashboard отрисовывается очень неспешно, в т.ч. и островки "Активностей", определенные элементы управления стадией и взаимодействия с активностями выполняют свою логику некорректно, вернее появившаяся после пользовательского действия SectionActionDashboard не отражает реального положения вещей, да и просто стилистические изменения произвести невозможно пока элементов нет в DOM.
Вот, мне и подумалось, что если вдруг имеется возможность, получить callback с callParent метода, то это было бы очень элегантным и простым решением задачи.
(По факту мы понимаем, что речь идет не о callback как таковом, а о добавлении своей функции в chain вызовов метода и его родительских )
А так приходится "колдовать" с ловлей изменения атрибута специфического, изучив внутреннюю логику схем.

Если сам метод спроэктирован так что бы принимать колбек в качестве параметра, и вызывать его после всех своих действий, то да, передавайте свой колбек в callParent и он будет вызван, но не все мтоды так спроектированы, к примеру SectionActionDashboard что вы указали, переданый колбек будет вызван ДО основной цепочки this.Terrasoft.chain(
Так что, тут ответ нет. Всегда смотрите реализацию метода что замещаете, и место где он вызывает колбек, и вызывает ли вообще.

"Максим Шевченко" написал:Всегда смотрите реализацию метода что замещаете, и место где он вызывает колбек, и вызывает ли вообще.

Это понятно.
просто была призрачная надежда что сам по себе механизм callParent что-то такое позволяет, по крайней мере предположить ситуацию логики отложенной на завершение вызова цепочки родителей - видится не такой уж и редко встречающейся.
Но изучить конкретно его механику сложно, потому что all-combined.js :)

Показать все комментарии

Нужно решить следующую задачу:
1. Создать новое рабочее место и раздел в нем.
2. На странице раздела должен выводиться список кастомных объектов, каждый из которых имеет id (внешний, не тот который в базе bpmonline), название и ссылку (должна быть кликабельна). Объекты должны подгружаться со стороннего API.

Первый пункт проблем не доставил. А вот второй... Я сам являюсь одним из разработчиков того стороннего API, поэтому сначала возникла идея просто выводить таблицу внутри айфрейма, однако руководство поставило задачу сделать более "умным" способом.

Я решил попытаться сделать деталь с пользовательскими полями по туториалу (https://academy.terrasoft.ru/documents/technic-sdk/7-10/sozdanie-polzova...) версия системы у меня 7.10б однако, следуя примеру, родительским объектом детали следовало указать Base fields detail из пакета BaseFinance, но у меня он не установлен, и не понятно, установить его, или же не стоит тащить целый пакет ради одного объекта. Пытался по-другому создать делаь и вывести список на страницу раздела, но ничего так и не получилося.

После создания детали и добавления списка на страницу раздела, планировал при загрузке страницы посылать AJAX-запрос по API, потом с помощью службы DataService вытащить существующие объекты, сравнить с получены ответом, и с помощью этой же службы удалить неактуальные и добавить новые, и таким образом обойтись без конфигурационных сервисов, так как совсем не знаком с языком С#.

Но, может быть, я пытаюсь двигаться совсем не туда? Прошу советов и подсказок, так как опыта работы с системою нету, все сложно и запутано, документация местам непонятна, колег, знакомых с системой, нету также. Буду признателен за подсказки, в какую сторону двигаться для реализации даного кейса.

Нравится

2 комментария

Я думаю вам правильнее будет сделать самый обыкновенный раздел мастером разделов на основании объекта, с текстовой колонкой для ссылки, и с текстовой колонкой для внешнего id (если он guid), или числовой, если число.
Сделать несколько доработок что бы ссылка была кликабельной и вела во внешнюю систему.

А наполнять данный раздел с помощью интеграции. И тут открывается множество вариантов. Будь то запрос во внешнюю систему, с переодичностью. Либо внешняя система будет сохранять данные в bpm посредством odata каждый раз как таковые будут там созданы. Либо написать веб сервис в bpm и вызывать его из внешней системы. С вариантами интеграции можете ознакомится здесь:
https://academy.terrasoft.ru/documents/technic-sdk/7-10/integraciya-s-s…

"Максим Шевченко" написал:

Я думаю вам правильнее будет сделать самый обыкновенный раздел мастером разделов на основании объекта, с текстовой колонкой для ссылки, и с текстовой колонкой для внешнего id (если он guid), или числовой, если число.

Сделать несколько доработок что бы ссылка была кликабельной и вела во внешнюю систему.

А наполнять данный раздел с помощью интеграции. И тут открывается множество вариантов. Будь то запрос во внешнюю систему, с переодичностью. Либо внешняя система будет сохранять данные в bpm посредством odata каждый раз как таковые будут там созданы. Либо написать веб сервис в bpm и вызывать его из внешней системы. С вариантами интеграции можете ознакомится здесь:

https://academy.terrasoft.ru/documents/technic-sdk/7-10/integraciya-s-si...


Спасибо, буду смотреть и пробовать.

Показать все комментарии

Всем доброго времени суток.
Версия 7.10.

Есть блок, в котором должна отображаться фотография контакта:

{
                                        "operation": "insert",
                                        "name": "SubscriberPhoto",
                                        /**/
                                        "values": {
                                                "itemType": Terrasoft.ViewItemType.BUTTON,
                                                "imageConfig": {"bindTo": "setContactPhoto"},
                                                "classes": {"wrapperClass": ["subscriber-photo"]},
                                                "style": Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
                                        }
                                },

Функция setContactPhoto сейчас вот такая:

setContactPhoto: function(photoId) {
                                        if ( (photoId == "Photo") || !photoId){
                                                return this.get("Resources.Images.UnidentifiedSubscriberPhoto");
                                        }
                                       
                                        var photoConfig = {
                                                source: this.Terrasoft.ImageSources.ENTITY_COLUMN,
                                                params: {
                                                        schemaName: "SysImage",
                                                        columnName: "Data",
                                                        primaryColumnValue: photoId
                                                }
                                        };
                                       
                                        return {
                                                source: Terrasoft.ImageSources.URL,
                                                url: Terrasoft.ImageUrlBuilder.getUrl(photoConfig)
                                        };
                                },

Также есть запрос, вытягивающий из контакта Contact колонку Photo. photoId в функции - отправляю value из колонки Photo в ответе на запрос данных из контакта.

Тем не менее всегда подставляется пустое значение UnidentifiedSubscriberPhoto, вне зависимости от того, есть фото у контакта, или нет.

Как исправить функцию, чтобы подстановка работала?

Нравится

3 комментария

Здравствуйте, посмотрите актуальную для 7.10 инструкцию:
https://academy.terrasoft.ru/documents/technic-sdk/7-10/dobavlenie-poly…
В особенности части где указывается поле изображения в объекте.

Здравствуйте. По ссылке не совсем то.. там речь идёт о поле для изображения на странице.

А если у нас нет своего объекта? Мы делаем карточку звонка, там должно быть изображение из контакта. Причём ссылка на него генерится через ImageUrlBuilder, заметил, что при этом только не изменяется изображение в блоке, остаётся та заглушка UnidentifiedSubscriberPhoto, которая выставлялась при первоначальной загрузке.

Как можно обновить блок?

Может быть есть тип виртуальной колонки Terrasoft.DataValueType и можно сделать динамическое изменение через атрибут?

Нашёл например такой тип Terrasoft.DataValueType.IMAGE - есть ли примеры работы с ним?

UPD. Сделал через виртуальную колонку - работает:

"contactImage": {
					"dataValueType": Terrasoft.DataValueType.IMAGE,
					"type": Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
				},
Показать все комментарии

Всем доброго времени суток.
Версия 7.10.

Данные о звонке записываются напрямую в базу (внутри схемы CTIPanel, если что). При этом на боковой ленте звонков во-первых отображается почему-то только последний звонок, во-вторых только после перезагрузки страницы в браузере.

Как обновить ленту без перезагрузки?

Нравится

3 комментария

Добрый день, Денис!

В истории звонков(на CTI-панели) доступна информация только о последнем соединении с определенным абонентом (контактом или контрагентом). Например, если вы позвонили одному и тому же контакту, но по разным номерам, указанным в блоке [Средства связи] на странице данного контакта, то в истории звонков отобразится одна запись по данному абоненту с указанием номера, по которому вы связывались с ним в последний раз.

Более подробно тут - https://academy.terrasoft.ua/documents/marketing/7-10/istoriya-zvonkov#…

По вопросу обновления страницы уточните выполнялись ли какие-либо доработки в bpm'online для телефонии и с каким интервалом были звонки одному и тому же абоненту ?

"Мотков Илья" написал:в истории звонков отобразится одна запись по данному абоненту

Илья, понятно, спасибо.

По обновлению вопрос немного не по телефонии даже... там запись происходит через insertQuery. В остальном можно считать что всё как из коробки. Нужно что-то типа updateDetail для деталей, но для блока со списком звонков.

Нашёл вот такую штуку - this.updateHistoryOnCallSaved(call) в CtiPanelModelUtilities.

Оно, нет? Нужно просто принудительно обновить историю звонков.

Показать все комментарии

Создал новое поле ITEmailв разделе контрагенты, добавил мапинг:
{
"CommunicationType": ConfigurationConstants.CommunicationTypes.Email,
"MasterEntityColumn": "ITEmail"
},
добавил атрибут:
"Email": {
"dependencies": [
{
"columns": ["ITEmail"],
"methodName": "syncEntityWithCommunicationDetail"
}
]
},
добавил поле в диф:
{
"operation": "insert",
"parentName": "ProfileContainer",
"propertyName": "items",
"name": "ITEmail",
"values": {
"layout": {"column": 0, "row": 7, "colSpan": 24}
}

},
добавил емаил в :
UseForAccounts: {
Predefined: {
Phone: {
displayValue: resources.localizableStrings.AccountPhone,
value: "6a3fb10c-67cc-df11-9b2a-001d60e938c6"
},
AdditionalPhone: {
displayValue: resources.localizableStrings.AdditionalPhone,
value: "2b387201-67cc-df11-9b2a-001d60e938c6"
},
Fax: {
displayValue: resources.localizableStrings.Fax,
value: "9a7ab41b-67cc-df11-9b2a-001d60e938c6"
},
Web: {
displayValue: resources.localizableStrings.Web,
value: "6a8ba927-67cc-df11-9b2a-001d60e938c6"
},
Email: {
displayValue: resources.localizableStrings.Email,
value: "ee1c85c3-cfcb-df11-9b2a-001d60e938c6"
}
},

в итоге значение в поле емаил детали подставляется в поле раздела и сохраняется, НО после того я захожу в контрагента, для которого был указан емаил, то значение в поле раздела пустое, а детали есть. Как можно сделать что бы оно не пропадало???

Нравится

2 комментария

Добрый день, Вам стоит смотреть в сторону добавления логики в событие после сохранения объекта AccountComunication. В частности, необходимо переопределить метод SetNewAccountCommunication.

"Мотков Илья" написал:

Добрый день, Вам стоит смотреть в сторону добавления логики в событие после сохранения объекта AccountComunication. В частности, необходимо переопределить метод SetNewAccountCommunication.


Здравствуйте, что то я не нашел такого метода в объекте AccountComunication, а в ContactComunication он есть. Там есть только GetColumnNameByCommunicationType:
string columnName;
switch (communicationType.ToString()) {
case CommunicationTypeConsts.WebId:
columnName = "Web";
break;
case CommunicationTypeConsts.MainPhoneId:
columnName = "Phone";
break;
case CommunicationTypeConsts.AdditionalPhoneId:
columnName = "AdditionalPhone";
break;
case CommunicationTypeConsts.FaxId:
columnName = "Fax";
break;
default:
columnName = string.Empty;
break;
}
я так понял что он мне подойдет, только не могу понять, надо в замещающем объекте сам метод переопределять?

Показать все комментарии

Обнаружено следующее поведение,
В некотором объекте н/п Tender есть поле н/п "Stage" (Справочное), на уровне конфигурации установлено значение по-умолчанию, н/п элемент с Name ='Создание'
В схеме карточки для этого поля в lookupListConfig добавляем "просмотр внутрь" и извлечение дополнительных полей выбранного элемента справочника.

...
attributes: {
"Stage": {
        lookupListConfig: {
                 columns: ["Name"]
        }
},
...

Так, открываем карточку существующей записи, н/п созданной и тут-же сохраненной, но повторно открытой в режиме редактирования
this.get("Stage");

получаем вполне ожидаемый результат
{value: "16886c2b-1388-45d3-9514-3ca70b9a4858", displayValue: "Создание", primaryImageValue: "", Name: "Создание"}

Так теперь просто открываем карточку в режиме создания и повторяем эксперимент:
this.get("Stage");

получаем результат неожиданный:
{value: "16886c2b-1388-45d3-9514-3ca70b9a4858", displayValue: "Создание"}

а где же наш Name который мы указали в lookupListConfig для нашего поля ?
про свойство primaryImageValue не ясно, но его как бы тоже нет.

И вот не ясно - так и должно быть, в силу каких-то более не менее объективных причин, или это выявленный дефект ?

Нравится

1 комментарий

Создали проблему для реализации данного функционала и при открытии карточки в режиме создания. Будет исправлено в рамках работы над новыми релизами. Тем временем можете проверять режим карточки и получать эти данные через esq.

Показать все комментарии

Пытаюсь создать схему представления детали с полями по примеру из https://academy.terrasoft.ru/documents/technic-sdk/7-10/sozdanie-polzova... . Версия системы - 7.10.1.1161. В данном примере из документации при создании схемы представления детали с полями в качестве базового объекта нужно указать Base fields detail ( BaseFinance ), однако в выпадающем списке он отсутствует. Никак не могу понять, что именно я делаю не так. Буду признателен за любую помощь/подсказки.

Нравится

1 комментарий

Проверьте, есть ли вообще в Вашей конфигурации такая схема, так как она есть только в банковских продуктах bpm'online — bank customer journey, bank sales и lending.
Если у Вас один из перечисленных выше продуктов и такая схема есть в Вашей конфигурации, тогда для того, чтобы её можно было указать в качестве базовой в Вашем пакете, Ваш пакет должен наследоваться от пакета Base Finance с этой схемой.

Показать все комментарии

Здравствуйте!

Передо мной стоит следующая задача: при создании лида проверять по полю "название контрагента" наличие уже существующих контрагентов с таким именем.
Создание лида идет из миникарточки.

Вопрос в том, как это сделать лучше, чтобы нагрузка была не очень большой на систему.
нужно чтобы ответ о наличии контрагента я получала до сохранения (синхронность)
существующие контрагенты проверяются как в правиле поиска дублей, например, допуская наличие/отсутствие кавычек, прописные/строчные буквы.
может возможно использование существующего поиска дублей для контрагентов, но только при создании лида и с синхронным ответом.
вроде как это можно сделать запросом через getEntityCollection, но там скорее всего уже будет большая нагрузка и вроде как условия по наличию/отсутствию кавычек и равенстве прописных и строчных букв там в условии не задать

было бы замечательно делать эту проверку сразу после заполнения поля "название контрагента", но я не знаю насколько это реализуемо.

Нравится

8 комментариев
Лучший ответ

"Zaitova Liubov" написал:и вроде как условия по наличию/отсутствию кавычек и равенстве прописных и строчных букв там в условии не задать

Сохраняйте для всех контрагентов в скрытом поле имя, по которому искать, убирая кавычки, приводя к UPPER, убирая всякие возможные части текста типа А/O, OOO и другие.

"Zaitova Liubov" написал:и вроде как условия по наличию/отсутствию кавычек и равенстве прописных и строчных букв там в условии не задать

Сохраняйте для всех контрагентов в скрытом поле имя, по которому искать, убирая кавычки, приводя к UPPER, убирая всякие возможные части текста типа А/O, OOO и другие.

Любовь, добрый день.

Любые механизмы поиска дублей, тем более с синхронным ответом, будут создавать нагрузку. То, что Вы хотите реализовать - это LIKE запрос по текстовому полю в таблице, в которой теоретически может быть и сто тысяч записей, и миллион. Скорее всего, Вы просто не получите ответ на клиенте за 30 секунд. Как по мне, более оптимальным вариантом является использованием существующего асинхронного механизма. запуская его, скажем, один раз в неделю.

"Мотков Илья" написал:

Любовь, добрый день.

Любые механизмы поиска дублей, тем более с синхронным ответом, будут создавать нагрузку. То, что Вы хотите реализовать - это LIKE запрос по текстовому полю в таблице, в которой теоретически может быть и сто тысяч записей, и миллион. Скорее всего, Вы просто не получите ответ на клиенте за 30 секунд. Как по мне, более оптимальным вариантом является использованием существующего асинхронного механизма. запуская его, скажем, один раз в неделю.


задача в двух словах в том, чтобы не дать создать лид, если такой(указанный в поле название контрагента) контрагент уже есть, просто если запускать этот механизм раз в неделю, это некорректно, так как по лиду уже будет запущен процесс, поэтому хотелось бы не исправлять проблему с наличием дубля,а предотвращать ее.

"Zaitova Liubov" написал:Вы хотите реализовать - это LIKE запрос по текстовому полю в таблице, в которой теоретически может быть и сто тысяч записей, и миллион.

а если делать как советовал Владимир Соколов:" Сохраняйте для всех контрагентов в скрытом поле имя, по которому искать, убирая кавычки, приводя к UPPER, убирая всякие возможные части текста типа А/O, OOO и другие.". то это уже будет equal, а не like и должно быть быстрее. все равно getEntityCollection не справится достаточно быстро? и еще вопрос - это вообще реализуемо, что можно дождаться его ответа и по результату дать/не дать сохранить?

Теоретически можно сделать что-угодно.)

Как заместить логику сохранения обсуждали буквально недавно: http://www.community.terrasoft.ru/forum/topic/25618
Можете аналогично переопределить метод save, и, допустим, строить запрос вида:
SELECT COUNT(*) FROM Account WHERE NAME = 'MyName', и если COUNT = 0 - сохранять запись, вызывая callParent. Однако, в таком случае Name в Контрагенте должен быть также без ООО, кавычек и прочего.

"Zaitova Liubov" написал:то это уже будет equal, а не like и должно быть быстрее

Боюсь, что для такой задачи даже Like недостаточно, нужно учиться у Google распознавать схожие записи, например "Аксиома" и "Аксиомаа"

"Мотков Илья" написал:Можете аналогично переопределить метод save

А может, лучше на Validation повесить?

"Владимир Соколов" написал:А может, лучше на Validation повесить?

Если можно логику выполнить синхронно то да, иначе:
http://www.community.terrasoft.ua/forum/topic/25618#comment-69035

Показать все комментарии