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

Я правильно понимаю, что можно все это реализовать через C# с использованием БП и его элемента "Задание-сценарий"? (задача - забрать из базы нужные данные и их потом обработать).

Просто не могу найти пример этой реализации. И почему на академии нет такой статьи - это было бы очень полезно.

 

 

Нравится

5 комментариев

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

Но, если решили из бизнес-процесса, то в элементе [Задание-сценарий] можно вызывать веб-сервис, который будет выполнять интеграцию.

Подробнее о более подходящем для Вашей задачи способе интеграции можно почитать здесь.

Также, начиная с версии 7.12 появился новый элемент процесса [Вызвать веб-сервис], в котором реализована пользовательская возможность подключения интеграции REST-сервисами. Об этом подробнее на Академии можно почитать в отдельном разделе.

Алла Савельева,

Просто мне показалось, что там описано больше именно о том как интегрироваться с BPM (и его объектами). Мне же хочется из BPM пойти в стороннюю БД (а это не совсем сторонний сервис). Не встречали именно такого примера? 

Если вторая база доступна из основной, то можно интегрироваться на уровне SQL. Настроить linked server, написать в основной базе view, работающие со второй, зарегистрировать по этой view схему с такими же колонками и далее работать с ней для чтения, как с обычной.

Если нужно туда ещё и писать, можно добавить в view триггеры II, IU, ID, которые пишут в таблицы второй базы. Или же сделать хранимку и запускать её из C#-скриптов в БП.

Зверев Александр,

А можно немного поподробней про последний вариант?

См. на сайте Microsoft: Linked Servers.

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

Появилась необходимость загружать пользователей из AD. Но количество атрибутов мало и хочется их увеличить. Стоит вопрос - как? Может кто занимался подобными доработками?

Нравится

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

Согласно базовой логики системы, Вы можете настроить синхронизацию своего поля в насстройках синхронизации LDAP, выбрав неиспользованное поле в bpm. К сожалению, настроить синхронизацию с созданным в bpmonline полем нельзя.

В старых версиях системы набор атрибутов, которые синхронизируются с LDAP? был статичен. Реализация была выполнена на уровне "ядра" приложения. Просто настройками этот набор изменить не получится.

В последних эту логику вынесли в схему LDAPUtilities, которую можно переопределить своей версией на уровне конфигурации. Но тогда этот механизм нужно будет самостоятельно поддерживать и адаптировать при обновлениях системы.

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

Добрый день!



Интересует вопрос: как показать модальное окно с картинкой? Точнее что для этого необходимо. Для примера взял https://marketplace.terrasoft.ru/app/new-year-motivation-bpmonline (процесс как раз показывает картинки), но не могу до конца разобраться что из всего является обязательным. По сути у меня уже есть справочник с картинками и описанием. Дальше надо в БП вызвать собственно само модальное окно (из картинки и текста). Для этого нужная страница этого модального окна и все? И как тогда его вызывать из БП?

Нравится

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

Быстров Сергей,

Вы правы, к сожалению, вызвать модальное окно пользовательскими средствами, используя существующую функциональность элементов процесса [Преднастроенная страница] и [Автогенерируемая страница] нельзя sad

Пример работы с модальным окном приведен в этом посте.

Если говорить о примере с картинками, который Вы приводили, то там для вызова окна с картинкой реализовано специальное действие процесса 'Показать окно с картинкой'.

А непосредственно вызов модального окна реализован в UsrImageScreenUtilities в функции openImageScreen.

Для решения Вашей задачи Вы можете либо вызвать уже реализованное кастомное модальное окно, используя элемент процесса [Преднастроенная страница], либо использовать элемент [Автогенерируемая страница] для настройки нужного окна.

Алла Савельева,

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

Есть отдельная сущность, модальное окно. Функции для работы с ним  — в схеме LookupUtilitiesV2.

Быстров Сергей,

Вы правы, к сожалению, вызвать модальное окно пользовательскими средствами, используя существующую функциональность элементов процесса [Преднастроенная страница] и [Автогенерируемая страница] нельзя sad

Пример работы с модальным окном приведен в этом посте.

Если говорить о примере с картинками, который Вы приводили, то там для вызова окна с картинкой реализовано специальное действие процесса 'Показать окно с картинкой'.

А непосредственно вызов модального окна реализован в UsrImageScreenUtilities в функции openImageScreen.

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

Коллеги, добрый день!

Подскажите, пожалуйста, возможно ли выполнить импорт данных из Excel в раздел [Сервисы] во вкладку "Файлы и ссылки" на деталь "Файлы и примечания" ?

В конфигураторе и мастере импорта найти объект не удаётся :(

Заранее спасибо!

Нравится

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

Если нужно импортировать в примечания, тогда импортировать нужно в саму таблицу [Сервисы] в поле "'Заметки".

А, если нужно во вкладку "Файлы и ссылки", то, чтобы не искать таблицу по названию, можно сразу выполнить импорт из детали через меню [Импорт данных]. Смотрите пример на Академии.

Если нужно импортировать в примечания, тогда импортировать нужно в саму таблицу [Сервисы] в поле "'Заметки".

А, если нужно во вкладку "Файлы и ссылки", то, чтобы не искать таблицу по названию, можно сразу выполнить импорт из детали через меню [Импорт данных]. Смотрите пример на Академии.

Алла Савельева,

спасибо!

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

Добрый день!

Не могу понять как изменить колонку для поиска по умолчанию. Если открывается lookup (this.openLookup(config, this.lookupCallback, this);) - то как изменить эту самую колонку с базового "Название" на "Полное имя"? Суть в том, чтобы когда открывалось окно - можно было сразу писать в поиске, а не выбирать каждый раз "Полное имя"

Изображение удалено.

Нравится

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

Можно просто в EntitySchema таблицы этого справочника изменить поле для отображения или же есть более сложный вариант - обсуждение посмотрите в посте.

Можно просто в EntitySchema таблицы этого справочника изменить поле для отображения или же есть более сложный вариант - обсуждение посмотрите в посте.

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

Добрый день!

Мне необходимо создать правило поиска дублей Сервисных договоров по полю Name.

Нашел пример в академии с созданием хранимой процедуры. 

https://academy.terrasoft.ru/documents/technic-sdk/7-13/dobavlenie-prav…

В ней указано:

INSERT INTO [ContactDuplicateSearchResult]. В моем случае таблицы [ServicePactDuplicateSearchResult] нет. Нужно ли ее создавать? В коробке правило поиска дублей работает только для контактов и контрагентов что ли?

Нравится

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

В коробке да реализованы правила поиска дублей, только по сущностям:

- Контакты

- Контрагенты 

- Лиды

Все остальное, это Кастомная доработка.

В коробке да реализованы правила поиска дублей, только по сущностям:

- Контакты

- Контрагенты 

- Лиды

Все остальное, это Кастомная доработка.

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

Но, в общем, реализация этой функциональности очень обьемна и сводится к следующему:



1. Создать процесс для поиска записей в своем разделе (аналогично процессу StartGlobalContactDuplicatesSearch).

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

3. Процедура будет записывать данные в созданный Вами объект MyObjectDuplicates (создайте объект по аналогии с объектом ContactDuplicate)

4. Необходимо создать новую страницу редактирования, которая будет отображать данные из созданного объекта MyObjectDuplicates по аналогии со страницей DuplicatesPageV2 (либо заместите DuplicatesPageV2, добавив в нее нужную логику).

ууу...

А вам надо именно поиск дублей или запрет создавать договоры с одинаковым именем?

Владимир Соколов,

в корень зрите, так тоже можно решить проблему)

Мотков Илья пишет:

Но, в общем, реализация этой функциональности очень обьемна и сводится к следующему:

1. Создать процесс для поиска записей в своем разделе (аналогично процессу StartGlobalContactDuplicatesSearch).

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

3. Процедура будет записывать данные в созданный Вами объект MyObjectDuplicates (создайте объект по аналогии с объектом ContactDuplicate)

4. Необходимо создать новую страницу редактирования, которая будет отображать данные из созданного объекта MyObjectDuplicates по аналогии со страницей DuplicatesPageV2 (либо заместите DuplicatesPageV2, добавив в нее нужную логику).

Уважаемые коллеги, подскажите, пожалуйста, подробнее (очень актуально)

1. Правильно ли я понимаю, что процесс надо создать уже с использованием своей хранимой процедуры "tcp_Find...", а не глобальной как  в процессе StartGlobalContactDuplicatesSearch

2. понятно

3. Правильно ли я понимаю, что здесь таблица, созданная непосредственно в SQL (без бизнес-объекта в Creatio, аналогично, например, AccountDuplicateSearchResult )

4. вот тут , пожалуйста, поподробнее, если возможно. Не получается разобраться со страницей DuplicatesPageV2, как связать новую страницу с новым объектом 

Хранимая процедура отрабатывает при запуске непосредственно в SQL, правило в интерфейсе Creatio появилось, но что нужно сделать (хотя бы концептуально) для работы страницы?

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

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

Система - bpm'online service enterprice 7.13 

Раздел Конфигурации(он же Продукты на других версиях) в карточке единицы конфигурации есть деталь Комплектация, где присутствует возможность добавить связанные продукты(ед. конфигурации).

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

Можно ли такое реализовать?

Нравится

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

Андреев Андрей Сергеевич,

Так, ну тогда можно попробовать следующий вариант:

1) Создаем контейнер и поле для поиска

{
                "operation": "insert",
                "name": "MyFilterContainer",
                "parentName": "LeftGridUtilsContainer",
                "propertyName": "items",
                "index": 0,
                "values": {
                    "id": "MyFilterContainer",
                    "itemType": this.Terrasoft.ViewItemType.CONTAINER,
                    "items": [],
                    "layout": {
                        "column": 25,
                        "row": 1,
                        "colSpan": 4
                    }
                }
            },
            {
                "operation": "insert",
                "parentName": "MyFilterContainer",
                "propertyName": "items",
                "name": "UsrEmail",
                "values": {
                    "bindTo": "UsrEmailFilter",
                    "caption": {"bindTo": "Resources.Strings.UsrEmailFilter"},
                    "layout": {
                        "column": 5,
                        "row": 2,
                        "colSpan": 4
                    },
                    "controlConfig": {
                        "change": {
                            "bindTo": "emailChanged"
                        }
                    }
                }
            }

2) Добавляем атрибуты

 

  attributes: {
            "UsrEmailFilter": {
                "dataValueType": Terrasoft.DataValueType.TEXT
            },
            "UsrEmails": {
                "dataValueType": Terrasoft.DataValueType.TEXT,
                "values": ""
            }
        },

3) Добавляем методы

 

emailChanged: function(a, b, c) {
                this.set("UsrEmails", a);
                this.onUsrFilterChanged();
                debugger;
            },
            clearFilter: function() {
                this.set("UsrEmailFilter", "");
                this.onUsrFilterChanged();
            },
 
            onUsrFilterChanged: function() {
                this.reloadGridData();
            },
 
            initQueryFilters: function(esq) {
                this.callParent(arguments);
 
                var usrEmailFilter = this.get("UsrEmails");
 
                if (usrEmailFilter) {
                    esq.filters.add("UsrEmailFilter", this.Terrasoft.createColumnFilterWithParameter(
this.Terrasoft.ComparisonType.CONTAIN, "[Account:Id].Email".substring(), usrEmailFilter));
                } else {
                    esq.filters.removeByKey("UsrEmailFilter");
                }
            }

Конкретно в данном примере вы на выходе получите поле для фильтрации контрагентов по Email.

Ваша же задача, доработать initQueryFilters, во первых заменить на продукты фильтр и дополнить значениям с детали.



Делаете esq запрос,с фильтрами, по названию, в примере выше есть, формируйте коллекцию Id записей, затем по этой коллекции, делайте еще одну выборку уже в деталь, на выходе получите еще одну коллекцию ID продуктов записей, дополните её значениями первой коллекции, после чего, весь этот массив данных передайте в initQueryFilters и через обычный for (i=0; collection.lenghr; i++) { постройте и верните filterGroup }

Можете скриншотами показать, что вы хотите? Как-то все запутано звучит.

Что касается, первой части "Поле для ввода" и "Кнопки" по нажатию на которой в гриде отобразить подходящие значения - реализовать можно, делается достаточно быстро.

В моем понимании этой части вашей задачи все выглядит так: есть раздел Контрагент => Ввел в нужном Поле например Наша компания => клик Найти => в гриде раздела отобразились все записи с названием "Наша компания".

Если верно, то что вы хотите во 2-ой части своего вопроса?

Литвинко Павел,

http://prntscr.com/lj4zpx

На скрине сама секция - Техника аки Конфигурации

1.Контейнер где должен располагаться фильтр(поле и кнопка)

2. Сущность секции аки Запись



http://prntscr.com/lj50rz

На этом скрине карточка сущности.

В выделенной области есть деталь Комплектующие где хранятся связи с другими такими же записями того же раздела



Суть фильтра такова.

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



Как сделать такого рода фильтрацию?

 

Андреев Андрей Сергеевич,

Так, ну тогда можно попробовать следующий вариант:

1) Создаем контейнер и поле для поиска

{
                "operation": "insert",
                "name": "MyFilterContainer",
                "parentName": "LeftGridUtilsContainer",
                "propertyName": "items",
                "index": 0,
                "values": {
                    "id": "MyFilterContainer",
                    "itemType": this.Terrasoft.ViewItemType.CONTAINER,
                    "items": [],
                    "layout": {
                        "column": 25,
                        "row": 1,
                        "colSpan": 4
                    }
                }
            },
            {
                "operation": "insert",
                "parentName": "MyFilterContainer",
                "propertyName": "items",
                "name": "UsrEmail",
                "values": {
                    "bindTo": "UsrEmailFilter",
                    "caption": {"bindTo": "Resources.Strings.UsrEmailFilter"},
                    "layout": {
                        "column": 5,
                        "row": 2,
                        "colSpan": 4
                    },
                    "controlConfig": {
                        "change": {
                            "bindTo": "emailChanged"
                        }
                    }
                }
            }

2) Добавляем атрибуты

 

  attributes: {
            "UsrEmailFilter": {
                "dataValueType": Terrasoft.DataValueType.TEXT
            },
            "UsrEmails": {
                "dataValueType": Terrasoft.DataValueType.TEXT,
                "values": ""
            }
        },

3) Добавляем методы

 

emailChanged: function(a, b, c) {
                this.set("UsrEmails", a);
                this.onUsrFilterChanged();
                debugger;
            },
            clearFilter: function() {
                this.set("UsrEmailFilter", "");
                this.onUsrFilterChanged();
            },
 
            onUsrFilterChanged: function() {
                this.reloadGridData();
            },
 
            initQueryFilters: function(esq) {
                this.callParent(arguments);
 
                var usrEmailFilter = this.get("UsrEmails");
 
                if (usrEmailFilter) {
                    esq.filters.add("UsrEmailFilter", this.Terrasoft.createColumnFilterWithParameter(
this.Terrasoft.ComparisonType.CONTAIN, "[Account:Id].Email".substring(), usrEmailFilter));
                } else {
                    esq.filters.removeByKey("UsrEmailFilter");
                }
            }

Конкретно в данном примере вы на выходе получите поле для фильтрации контрагентов по Email.

Ваша же задача, доработать initQueryFilters, во первых заменить на продукты фильтр и дополнить значениям с детали.



Делаете esq запрос,с фильтрами, по названию, в примере выше есть, формируйте коллекцию Id записей, затем по этой коллекции, делайте еще одну выборку уже в деталь, на выходе получите еще одну коллекцию ID продуктов записей, дополните её значениями первой коллекции, после чего, весь этот массив данных передайте в initQueryFilters и через обычный for (i=0; collection.lenghr; i++) { постройте и верните filterGroup }

Литвинко Павел,

Спасибо большое!

Чекните ЛС плз.

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

Коллеги, требуется помощь.

Добавляю в VisualStudio2017 ссылку на сервис /0/ServiceModel/EntityDataService.svc/,ввожу логин и пароль, нажимаю далее - и высвечивается ошибка (рис 0001.1 и 0001). В сообщении выдаётся ссылка на документацию http://odata.github.io/odata.net/#OData-Client-Code-Generation-Tool

Если вводить адрес сервера в строку браузера - то после авторизации отврывается нормальный xml (рис. 0003)

Как поправить ошибку?

Заранее благодарен.

Прикрепленные файлы

Нравится

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

Есть инструкция по созданию прокси-классов, проверьте, может, что-то упустили.

Также, если есть доступ к бинарникам сайта, вместо EntityDataService из своей программы можно работать посредством DataService, как описано тут.

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

Есть правило видимости, делать поле видимым в зависимости от значения другого поля.

Все работает

Terrasoft.sdk.Model.addBusinessRule("Account", {

    ruleType: Terrasoft.RuleTypes.Visibility,

    conditionalColumns:

        [

            {name: "UsrStage", value: "a5d0ceac-3ef4-45e0-be25-af3a1190f6f9"}

        ],

        triggeredByColumns: ["UsrStage"],

        dependentColumnNames: ["UsrInstalationDate"]

    }

);

Как сделать такое же правило, но для признака "обязательно для заполнения".

То есть это же самое поле, при таких же условиях должно становиться еще и обязательным для заполнения.

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

 

 

Нравится

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

Requirement правило не поможет в данном случае. Нужно использовать Custom. Что-то вроде этого.

Terrasoft.sdk.Model.addBusinessRule("UsrMyModel", {
    name: "RuleName",
    ruleType: Terrasoft.RuleTypes.Custom,
    triggeredByColumns: [/*Список колонок, которые активируют правило*/],
    events: [Terrasoft.BusinessRuleEvents.Load, Terrasoft.BusinessRuleEvents.ValueChanged, Terrasoft.BusinessRuleEvents.Save],
    executeFn: function(record, rule, column, customData, callbackConfig) {
        var hasError = false; //булевая переменная, указывающая корректность поля.
        var errorMessage = "Необходимо указать значение."; // Сообщение об ошибке.
        //Выполняем нужный код, определяющий наличие ошибки
        record.changeProperty("UsrMyColumn", {
            isValid: {
                value: hasError,
                message: errorMessage
            }
        });
        Ext.callback(callbackConfig.success, callbackConfig.scope);
    }
});

 

Обязательность задаётся как Terrasoft.RuleTypes.Requirement. В конфигурации есть много примеров использования. Например, в MobileContactAddressModelConfig так:

Terrasoft.sdk.Model.addBusinessRule("ContactAddress", {
    name: "ContactAddressRequirementRule",
    ruleType: Terrasoft.RuleTypes.Requirement,
    requireType: Terrasoft.RequirementTypes.OneOf,
    triggeredByColumns: ["Address", "City", "Country"],
    position: 3
});

 

Поясните, что сделает это правило? Все колонки указанные в triggeredByColumns буду обязательные? Мне примерно также нужно, только в зависимости от значения определенного поля.

Requirement правило не поможет в данном случае. Нужно использовать Custom. Что-то вроде этого.

Terrasoft.sdk.Model.addBusinessRule("UsrMyModel", {
    name: "RuleName",
    ruleType: Terrasoft.RuleTypes.Custom,
    triggeredByColumns: [/*Список колонок, которые активируют правило*/],
    events: [Terrasoft.BusinessRuleEvents.Load, Terrasoft.BusinessRuleEvents.ValueChanged, Terrasoft.BusinessRuleEvents.Save],
    executeFn: function(record, rule, column, customData, callbackConfig) {
        var hasError = false; //булевая переменная, указывающая корректность поля.
        var errorMessage = "Необходимо указать значение."; // Сообщение об ошибке.
        //Выполняем нужный код, определяющий наличие ошибки
        record.changeProperty("UsrMyColumn", {
            isValid: {
                value: hasError,
                message: errorMessage
            }
        });
        Ext.callback(callbackConfig.success, callbackConfig.scope);
    }
});

 

Бершеда Д. Н.,

Спасибо за ответ.

Можно, пожалуйста, на простом примере объяснить?

 

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

Добрый день!



Решаем следующую задачу: интеграция bpm с внешней системой для синхронизации контактов. 



Имеются порядка 40к контактов из AD, BS и ручной загрузки. Все они собраны в одной системе и обновляются там автоматически. Стоит вопрос - как лучше проводить синхронизацию контактов bpm?



Стоит ли добавлять контакты в почту Exchange и использовать готовый процесс по синхронизации или лучше использовать другие варианты? И какие вообще существуют возможные способы интеграции?

Нравится

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

Если не в Exchange, можно придумать самые различные способы синхронизации: из внешней системы работать с веб-сервисами bpm'online по OData или DataService. Или наоборот, из bpm'online периодически обращаться к сервисам внешней системы. Если есть доступ в базу bpm'online, можно напрямую писать в таблицы контактов и деталей. Или то же самое, но с использованием шлюзовых таблиц.

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