Добрый день!
1. Скажите, пожалуйста, в каких таблицах хранятся процессы, запущенные экземпляры процессов, журнал процессов
2. Есть ли где-то описание физической структуры данных базы bpm (схемы таблиц, связи, описание столбцов)

Нравится

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

Добрый день!

1. Это таблицы:

- SysProcessData;
- SysProcessElementData
- SysProcessLog
- SysProcessElementLog

2. Вся доступная информация есть на SDK: http://www.terrasoft.ua/bpmonlinesdk/
Выбрать в меню пункты:
BPMonline SDK/ Сборки/ Terrasoft.Common - сборка/ Terrasoft.Common - пространства имен/ Terrasoft.Common/ Terrasoft.Common - классы
Это описание наших объектов а не структурных сущностей базы bpm.

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

Добрый день!
Версия omnichannel 7.5.0.1122
Есть пользовательский пакет Custom 7.5.0.1122, в котором можно добавлять собственные схемы и т.п.
При создании нового бизнес-процесса(например, в дизайнере процессов)
происходит задублирование этого пакета. Появляется точно такой же пакет с таким же названием, в котором хранится схема процесса.
Почему это происходит?
Во вложении - скриншот

Нравится

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

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

Так происходит, вероятно, потому, что система не знает, есть ли в ней пользовательский пакет Custom.

Попробуйте выполнить следующее:

1) Экспортировать в файл все схемы в НОВОМ пользовательском пакете Custom.
2) Удалить НОВЫЙ пользовательский пакет Custom.
3) Установить значением системной настройки с кодом CustomPackageUId СТАРЫЙ пользовательский пакет Custom.
4) Перезапустить сайт, очистить Redis.

Добрый день!
Подскажите, пожалуйста, как выполнить пункт 1 - перенести схему БП из нового пользовательского пакета в старый пользовательский пакет

Дарья,

сфокусируйтесь на схеме процесса, перейдите на вкладку Действия, выберите действие "Экспорт в файл".

После этого сфокусируйтесь на старом пользовательском пакете и выполните действие "Импорт из файла".

Также Вы можете открыть схему Вашего процесса и в его свойствах найти свойство "Пакет", где указать другой "Custom", после чего выполнить публикацию.

Новый пользовательский пакет удалила, настройку занесла(она в принципе и была), redis почистила. При создании бизнес-процесса опять создается пользовательский пакет-дубль

значение системной настройки уже было установлено, redis почистила - все равно дублируется

Дарья,

если попробовать убрать значение системной настройки, после чего очистить Redis?

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

Дарья,

в продолжение нашего телефонного разговора, ошибка исправлена в версии bpm'online 7.6 .

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

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

Поступили такие требования:
1. Реализовать деталь, где отображалась бы история изменения определённых полей (помеченных как "Вести историю изменений") в сущности. Желательно, чтобы была возможность фильтровать поля в закладке по имени поля и дате. Есть ли такой стандартный компонент / как это реализовать?

2. Добавить в детали (карточка? ещепутаюсь с терминологией) сущности исторические поля "Modified By" (user) и "Modified On". Я видел, что такие стандарные поля ("CreatedOn, CreatedBy, ModifiedOn, ModifiedBy") есть и создаются автоматически системой. Я могу их добавить в реестр (где сущности отображаются в виде списка), но не могу добавить в детали самой сущности - их нет в списке. Подскажите, как это сделать. Update. Уже увидел, что можно ручками добавить это поле в разметку карточки, нашел такие в Knowledge Base. Однако, может есть более простой способ, из UI в визарде секций?

Заранее благодарю!

Нравится

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

Здравствуйте! По поводу первого вопроса, данный функционал реализован в базовой версии приложения. Вашу бизнес-задачу можно решить посредством журнала изменений, который находится в "Управление конфигурацией" (Рис. 1).

 

 

Рис. 1

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

Это лучше, чем ничего, однако боюсь, это не тот функционал, что хотят заказчики. Они хотят, чтобы на карточке сущности (например, "Вакансия") была закладка "История", и там отображались изменения, касающиеся логируемых полей именно этой сущности, с возможностью видеть, когда были изменения, кто их произвёл, что было в поле до изменения, и новое значение. И чтобы для этого не нужно было заходить в "Advanced Settings", доступ к которым есть только у админов BPM, не говоря уже про неудобство. Вот пример подобного функционала в HP продукте Quality Center / ALM, с которым я работал в прошлом.

History tab

Есть что-нибудь подобное?

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

Спасибо!

Можно попробовать следующим образом:

1) Настроить логирование нужной схемы, например Contact. Это создаст таблицу SysContactLog.

2) Создать в конфигурации объект представления VwSysContactLog, и скрипт для создания представления в бд.  

 

 

 

3) Создать мастером деталь, которая выводит данные из представления VwSysContactLog

 

 

4) Добавить деталь мастером раздела на карточку.

 

 

 5) Настроить реестр новой детали – и все ок.

 

 

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

"Вильшанский Дмитрий" написал:2) Создать в конфигурации объект представления VwSysContactLog, и скрипт для создания представления в бд.

А не планируется этот ChangeLog вынести в пользовательский интерфейс, как было в 3.х, чтобы не создавать руками для всего?

"Владимир Соколов" написал:
Вильшанский Дмитрий пишет:

2) Создать в конфигурации объект представления VwSysContactLog, и скрипт для создания представления в бд.

А не планируется этот ChangeLog вынести в пользовательский интерфейс, как было в 3.х, чтобы не создавать руками для всего?


Владимир, здравствуйте!

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

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

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

Стоит задача реализовать внесение фирменного шаблона в создаваемые письма.
Теоретически можно сделать, как предложено здесь:
https://community.terrasoft.ru/blogs/7765

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

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

Нравится

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

Говорят, в 7.6 будет мощный движок шаблонов писем, в том числе и персонифицированных.

Послушаем завтра :-)

Фариз Эльдарович, здравствуйте!

На данный момент шаблоны E-mail сообщений могут быть настроены только через справочник "Шаблоны e-mail сообщений".

Нововведения в версии 7.6 касательно e-mail будут относиться к продуктам Service и Merketing.

Спасибо

Ок, а шаблоны email сообщений из справочника могут быть применены к любому вновь создаваемому письму?

Фариз Эльдарович,

справочник "Шаблоны e-mail сообщений" используется только при рассылках (Например в Sales + Marketing).

Существует другой способ настройки персонализации через БП - через элементы "Чтение данных" и "Отправить e-mail" (Таким образом будет некий аналог макроса).

Спасибо!

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

Добрый день!

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

Как можно реализовать аналогичный функционал в версии 7.3?

Нравится

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

Александра, добрый день!

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

Спасибо!

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

Коллеги, здравствуйте!

Дано: подготовленная Excel-таблица выставленных счетов, но наименования контрагентов отличаются по написанию с теми, что внесены в базу. Однако есть поле "код" контрагента, уникальное и однозначно идентифицирующее контрагента независимо от того как он написан.

Однако существующий механизм импорта в 7.5 не позволяет учесть поля, которые не существуют в разделе "Счет" напрямую (в 3.Х кстати был посильнее механизм Excel импорта :-)).

Я правильно понимаю, что если добавить в раздел "Счет" поле "Контрагент.Код" то можно будет по нему при импорте синхронизировать импортируемые счета со справочником контрагентов?

Если да, подскажите, как такое поле добавить в конфигураторе, сходу не обнаружил.

Нравится

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

Добрый день!

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

А можно как-то настроить, чтобы при добавлении нового имени контрагента, добавлялся и код? чтобы потом оперативно поиском дублей все почистить?

Если при импорте счетов - то контрагенты создаются по имени и в этом случае код добавить нельзя.
Если происходит просто импорт контрагентов - то в шаблонном Excel файле нужно указать код.

Если одноразовое действие, то, возможно, у объекта Контрагенты можно поменять поле для отображения на код, сделать импорт, а потом поменять обратно.

Владимир, можете раскрыть ваше предложение поподробнее?

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

Добрый день, подскажите где искать алгоритм происходящий после нажатия на зеленую трубку в детали средства связи
http://goo.gl/It5cS1
необходимо добавить дополнительные параметры при создания звонка

Нравится

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

Нажатие на кнопку обрабатывается в CTIBaseCommunicationViewModel функцией onLinkClick: function()

Не нашел там такой функции, есть

/**
 * Совершает звонок по текущему номеру телефона.
 * @protected
 */
call: function() {
	var number = this.get("Number");
	var contact = this.get("Contact");
	var customerId = contact ? contact.value : this.get("Account").value;
	var entitySchemaName = contact ? "Contact" : "Account";
	this.sandbox.publish("CallCustomer", {
		number: number,
		customerId: customerId,
		entitySchemaName: entitySchemaName
	});
},

кто то может подсказать где принимается этот CallCustomer?

CallCustomer - в BaseCommunicationDetail

нашел только это в BaseCommunicationDetail

messages: {
	"CallCustomer": {
		mode: Terrasoft.MessageMode.PTP,
		direction: Terrasoft.MessageDirectionType.PUBLISH
	},
	"DoNotUseCommunication": {
		mode: Terrasoft.MessageMode.PTP,
		direction: Terrasoft.MessageDirectionType.PUBLISH
	}
},

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

Добрый день.
Если я правильно понял, речь идет о 7.4.0 (cti-панель находится слева).
Вы все верно нашли - отправляется сообщение "CallCustomer", c параметрами: номер, идентификатор абонента и название объекта (Контакт или Контрагент).

Обрабатывается сообщение в схеме CtiPanelPage, метод onCallCustomer:

/**
 * Обработчик события звонка клиенту.
 * @param numberInfo {Object} Информация о параметрах звонка.
 * @param numberInfo.number {String} Номер телефона клиента.
 * @param numberInfo.isConsultCall {Boolean} Консультационный звонок.
 * @param numberInfo.isCanvassCall {Boolean} Звонок по исходящей кампании.
 * @param numberInfo.customerId {String} Id записи клиента.
 * @param numberInfo.callCampaignId {String} Id исходящей кампании.
 * @param numberInfo.callCampaignTargetId {String} Id целевой аудитории исходящей кампании.
 * @param numberInfo.callActivityId {String} Id активности.
 * @private
 */
function onCallCustomer(numberInfo) {
	if (!Ext.isEmpty(ctiModel.get("CurrentCallNumber")) && !Ext.isEmpty(ctiModel.get("ConsultCallNumber"))) {
		return;
	}
	if (!Ext.isEmpty(ctiModel.get("CurrentCallNumber"))) {
		if (numberInfo.number === ctiModel.get("CurrentCallNumber")) {
			return;
		} else {
			numberInfo.isConsultCall = true;
		}
	}
	var customerId = numberInfo.customerId;
	if (!numberInfo.isConsultCall && Ext.isEmpty(ctiModel.get("CurrentCallNumber"))) {
		var callLaterControlContainer = Ext.getCmp("callLaterControlContainer");
		if (callLaterControlContainer.rendered && !callLaterControlContainer.el) {
			callLaterControlContainer.rendered = false;
		}
		ctiModel.set("isCanvassCall", numberInfo.isCanvassCall);
		ctiModel.set("callCampaignId", numberInfo.callCampaignId);
		ctiModel.set("callCampaignTargetId", numberInfo.callCampaignTargetId);
		ctiModel.set("callActivityId", numberInfo.callActivityId);
		caller = numberInfo.number;
		callerInfo = null;
		if (Terrasoft.isGUID(customerId)) {
			ctiModel.set("customerId", customerId);
		}
		ctiModel.dial(numberInfo.number);
	} else if (numberInfo.isConsultCall && Ext.isEmpty(ctiModel.get("ConsultCallNumber"))) {
		ctiModel.transfering();
		if (!ctiModel.set("isModalWindowOpened")) {
			ctiModel.showModalWindow();
		}
		if (Terrasoft.isGUID(customerId)) {
			ctiModel.set("consultCustomerId", customerId);
		}
		ctiModel.callConsultCustomer(numberInfo.number);
	}
}

Можете добавить дополнительные свойства в numberInfo и обработать их в расширенной схеме CtiPanelPage.

Добрый день, почти то что нужно, метод вызывается из детали CommunicationDetail, он отправляет сообщение CallCustomer, эту деталь добавили на страницу активности и вопрос собственно заключается в том как связать Актиность со звонком, в объекте Call есть поле ActivityId вот как туда передать Id активности из которой был сделан звонок, на каком этапе задаются параметры numberInfo не могу найти перекопал уже все файлы что мог заподозрить в связи со звонками

Олег, к сожалению на этапе совершения звонка, еще не существует записи в таблице Call. Она появится уже после того, как телефония отправит сообщение о начале звонка в cti-панель.
Вы можете сделать по аналогии с тем, как происходит сохранение ссылки на кампанию обзвона, а именно сохранить ссылку на ActivityId в модели в onCallCustomer, а затем записать собственно в объект звонка в методе updateCall схемы CtiPanelPage

updateCall: function(columnName, customerId) {
	// ...
	var activityId = ctiModel.get("activityId");
	if (activityId) {
		update.setParameterValue("Activity", activityId,
			Terrasoft.DataValueType.GUID);
		ctiModel.set("activityId", null);
	}
	update.execute();
},

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

спасибо, это понял, но вот последний вопрос как передать параметр activityid в numberinfo и собственно на модель? в подписке на сообщение CallCustomer в CtiPanelPage есть

ctiModel.set("callActivityId", numberInfo.callActivityId);

откуда он берет айди активности?

Собственно мы его передаем, когда отправляем сообщение CallCustomer откуда-либо:
1. http://www.community.terrasoft.ru/forum/topic/12519#comment-53353

this.sandbox.publish("CallCustomer", {
		number: number,
		customerId: customerId,
		entitySchemaName: entitySchemaName,
// Передаем идентификатор активности
		callActivityId: <id активности>
});

2. Далее http://www.community.terrasoft.ru/forum/topic/12519#comment-53359

function onCallCustomer(numberInfo) {
	// ...
	// Это уже есть
	ctiModel.set("callActivityId", numberInfo.callActivityId);
	// ...
}

3. И наконец наш http://www.community.terrasoft.ru/forum/topic/12519#comment-53372

updateCall: function(columnName, customerId) {
        // ...
        var activityId = ctiModel.get("callActivityId");
        if (activityId) {
                update.setParameterValue("Activity", activityId,
                        Terrasoft.DataValueType.GUID);
                ctiModel.set("callActivityId", null);
        }
        update.execute();
},

Спасибо большое, а есть ли возможность перед публикации сообщений вытащить как то айди активности, объект this никаких связей с тем откуда от вызван в том моменте не содержит

Ну получение id активности уже зависит от того, как Вы реализовали деталь в карточке Активности.
Для контактов или контрагентов достаточно из модели взять атрибут "Contact" или "Account" соответственно. Могу предположить, что у Вас это какой-нибудь "Activity".

Артем, я не много не так выразился, наверное, в CTIBaseCommunicationViewModel.js мы собираем переменные для сообщения, вот как туда передать айди активности, к примеру там есть обращение к this но это обращение к объекту на детали

var number = this.get("Number");
var contact = this.get("Contact");

Олег, мы немного отошли от темы звонка и перешли к теме создания детали в карточке активности.
CTIBaseCommunicationViewModel - это view-модель средства связи, которая создается в NUI.BaseCommunicationDetail. Там же инициализируются атрибуты модели, такие как CommunicationTypes, DetailColumnName, PhoneCommunicationTypes. Вот где-то там Вам нужно также передать активность в качестве дополнительного атрибута, который затем читать в CTIBaseCommunicationViewModel.

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

Намагаюся розібратися зі скриптом [PageLoadCompleteScriptTask].
В ньому використовуються значення полів, взяті наступним чином:

Page.ProductCategoryEdit.Value;
Page.HasAnalogsCheckBox.Checked;
Page.IsAdditionalHandlingRequiredCheckBox.Checked;
...

Значення отримую нульові, або інакше - в них ще не відобразилися значення з DataSource.
Якщо зчитати відповідні значення з DataSource, то все гаразд, є значення.
Але таке застосування не буде коректним.

Коли значення описаних полів ([Page...]) використовую у відповідному обробнику, що був описаний в [InitScriptTaskExecute], то на цьому етапі значення вже присутні.

Запитання: в який момент прописуються значення описаних полів ?
Куди потрібно прописувати логіку, яка спирається на вказані значення ?
Чи, що треба зробити, щоб поля гарантовано отримали свої значення ?

Нравится

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

Игорь, здравствуйте!

"Ігор Андрусенко" написал:в який момент прописуються значення описаних полів ?

Значение интерфейсных полей изначально прописываются на клиентской части при помощи DataSource. Определение значений на сервере происходит, когда страница вернется с клиентской части.

"Ігор Андрусенко" написал:Куди потрібно прописувати логіку, яка спирається на вказані значення ?

Логику можно прописывать, например, на событиях изменений значений полей, на подготовку фильтров Lookup полей.
Не могли бы Вы описать логику применения значений полей и почему Вас не устраивает использование DataSource?
Спасибо

"y.perevjazko" написал:Не могли бы Вы описать логику применения значений полей и почему Вас не устраивает использование DataSource?

Мабуть справа в організації процесу оновлення полів.

На карточці заявки на внесення змін є пара полів типу дата.
Значення дат розраховуються в методі SetDeadlineDate().

Якщо метод запускається з якого-небудь обробника, то значення в полях фіксуються, в разі якщо обробник відпрацьовує.

А якщо метод запускається в скрипті PageLoadCompleteScriptTaskExecute,
то значення залишаються не зафіксованими.

Я так розумію, що обробник відпрацьовує по AJAX і дає миттєвий результат, а результат відпрацювання по скрипту фіксується після ситуативного надсилання даних на сервер.

Тому зараз запитання я б сформулював наступним чином:
Як заставити здійснити відправку даних на сервер не через обробник зміни значення якогось поля, а в примусовому порядку, у скрипті PageLoadCompleteScriptTaskExecute ?

Сделайте методу булевский параметр, на PageLoadComplete запускаете SetDeadlineDate(true), из других мест — SetDeadlineDate(false). Внутри метода в зависимости от параметра пишите или в поле датасорса (на PageLoadComplete), или в контрол на карточке.

Дещо "косим" способом запускаю метод:
вставив метод SetDeadlineDate() у скрипт обробки повідомлення SetTaskOwnerButtonClick (натиснення кнопки "Установить Content-менеджера").
При натисненні кнопки метод відпрацьовує, візуально значення змінюється.

Але далі отримав наступну мороку:
коли при першому натисненні кнопки вичитую його обома способами:

Page.DeadlineDateEdit.Value
Page.DataSource.ActiveRow.GetTypedColumnValue<DateTime>("DeadlineDate");

то отримую незмінене значення, не те, що в цей момент видно в полі карточки.
Вже коли вікно вибору менеджерів закриваю і потім повторно натискаю кнопку, тоді вичитується значення, яке було підставлене при попередньому натисненні-відпрацюванні SetDeadlineDate().

Це я вже з огляду на даний факт писав про AJAX.
Тому й питання щодо примусової відправки даних на сервер залишається актуальним, бо необхідність двічі розкривати вікно вибору Content-менеджерів навряд чи порадує виконавців.

Что это за окно выбора менеджеров? Оно открывается по кнопке? Как оно связано с полем?
Какой это продукт?

Так по кнопці відкривається вікно OwnerSelectionGridPage
З полем воно пов"язане таким чином:

UserConnection.SessionData["customDeadLine"] = Page.DeadlineDateEdit.Value;

Продукт: ServiceDesk
Я так розумію, що це додаткова розробка.

Але зважаючи на те, що при першому натисненні кнопки значення поля DeadlineDateEdit залишається неоновленим, то й у вікно передається неактуальне значення.
При другому - актуальне.

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

Рекомендуется всюду присваивать через

Page.DataSource.ActiveRow.SetColumnValue("DeadlineDate", DeadlineDate);

а не

Page.DeadlineDateEdit.Value = DeadlineDate;

Значення прописується ось так:

Page.DeadlineDateEdit.SetValue(deadlineDate);

Я так собі уявляю процес:
Значення прописується на боці клієнта, без відправки на сервер.
Тому не обновляється DataSource і, відповідно, зчитується не оновлене значення.
А при відкритті/закритті вікна по кнопці відбувається відправка даних, тому при наступному відпрацюванні SetDeadlineDate() показує, що значення вже оновлені.

А если заменить на Page.DataSource.ActiveRow.SetColumnValue ?

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

Добрый день!

Подскажите, где можно получить информацию классе Entity, и о его методах в частности? На удивление, в SDK этой информации не нашел :(

Нравится

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

Добрый день, Николай!
На данный момент класс Entity находится в процессе review.
Если у Вас есть точечные вопросы по какому-то методу – будем рады объяснить его предназначение с примерами использования.

С уважением, техподдержка «Террасофт»

Здравствуйте, Николай!

В папке с дистрибутивом есть папка Terrasoft.WebApp, в ней в папке bin лежат библиотеки (dll-файлы), которые вы можете добавить в проект в Visual Studio и затем посмотреть классы в данных библиотеках со всеми методами, свойствами, типами и так далее (скриншот во вложении). Либо можете посмотреть структуру любой другой программой для просмотра dll библиотек.

Александр, спасибо большое - то, что нужно!

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

Добрый день!
В разделе создано действие, при нажатии на которое запускается бизнес-процесс.
Смысл бизнес-процесса состоит в том, что в нем необходимо вызвать хранимую процедуру.
Т.е. бизнес-процесс состоит из трех элементов:
начальное простое событие
задание-сценарий
завершающее событие.

Вопросы:
1) как правильно вызвать хранимую процедуру
StoredProcedure storedProcedure = new StoredProcedure(UserConnection, "tsp_test") as StoredProcedure;
storedProcedure.PackageName = UserConnection.DBEngine.SystemPackageName;
storedProcedure.Execute();
return true;

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

2) как правильно передавать параметры входящие в процедуру(вызывать процедуру с параметрами)
и как правильно получить исходящие параметры хранимой процедуры

3) как правильно передавать в скрипте параметры БП во входящие параметры хранимой процедуры

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

Нравится

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

Добрый день, Дарья!

1) Правильный вызов процедуры (пример):

DataValueTypeManager dataValueTypeManager = UserConnection.DataValueTypeManager; 
var dateTimeValue = new DateTime(2009, 01, 02, 22, 12, 0);
                    Stream stream = new MemoryStream(Encoding.Unicode.GetBytes("Тест большого бинарного объекта"));
                    var textDataValueType = new TextDataValueType(dataValueTypeManager);
                    var guidDataValueType = new GuidDataValueType(dataValueTypeManager);
                    var integerDataValueType = new IntegerDataValueType(dataValueTypeManager);
                    var floatDataValueType = new Float2DataValueType(dataValueTypeManager);
                    var booleanDataValueType = new BooleanDataValueType(dataValueTypeManager);
                    var dateTimeDataValueType = new DateTimeDataValueType(dataValueTypeManager);
                    var idValue = new Guid("{BCDB8392-55BC-472A-A49D-22A975E0BEF6}");
 
                    StoredProcedure storedProcedure =
                           new StoredProcedure(Page.UserConnection, "tsp_TestStoredProcedure")
                           .WithParameter("IdParameter", idValue)
                           .WithVarParameter("VarIdParameter", idValue, guidDataValueType)
                           .WithParameter("TextParameter", "Украина")
                           .WithVarParameter("VarTextParameter", "Украина", textDataValueType)
                           .WithParameter("IntegerParameter", 10)
                           .WithVarParameter("VarIntegerParameter", 10, integerDataValueType)
                           .WithParameter("FloatParameter", 3.14)
                           .WithVarParameter("VarFloatParameter", 3.14, floatDataValueType)
                           .WithParameter("BooleanParameter", true)
                           .WithVarParameter("VarBooleanParameter", false, booleanDataValueType)
                           .WithParameter("DateTimeParameter", dateTimeValue)
                           .WithVarParameter("VarDateTimeParameter", dateTimeValue, dateTimeDataValueType)
                           .WithParameter("BinaryParameter", stream)
                           .WithVarParameter("VarBinaryParameter", stream)
                           .WithOutputParameter("ResultParameter", textDataValueType) as StoredProcedure;
storedProcedure.PackageName = Page.UserConnection.DBEngine.SystemPackageName;
storedProcedure.Execute();

2. Исходящий параметр .WithOutputParameter
3. Передача параметров в хранимую процедуру описана в первом пункте.
4. Вызов хранимой процедуры, Вы можете посмотреть в BaseAdministrativeGridPage

Спасибо.

по поводу пункта № 1- как правильно вызвать процедуру.

) Вызываю по аналогии в сценарии в БП
(процедура пока без параметров)

StoredProcedure storedProcedure = new StoredProcedure(UserConnection, "tsp_test") as StoredProcedure;
storedProcedure.PackageName = UserConnection.DBEngine.SystemPackageName;
storedProcedure.Execute();
return true;

Выходит ошибка при публикации (см. вложение).
Что не так?

2) по поводу пункта № 3 - не поняла.
Как передать просто параметры входящие - понятно.
Но как в скрипте правильно обратить к параметру бизнес-процесса, чтобы его уже значение передать в параметр хранимой процедуры ?

3) где именно искать вызов хранимой процедуры в BaseAdministrativeGridPage?

1. Код помещенный в БП в ScriptTask:

StoredProcedure storedProcedure = new StoredProcedure(UserConnection, "tsp_test") as StoredProcedure;
storedProcedure.PackageName = UserConnection.DBEngine.SystemPackageName;
storedProcedure.Execute();
return true;
не вызывает ошибки компиляции. Возможно у Вас есть еще какой-то код, который приводит к ошибке?

2. По имени параметра
var temp = ProcessSchemaParameter1

3. Поиском в исходных кодах
Открыть схему. Кнопка «Дополнительно» пункт меню «Открыть исходный код»

Спасибо, я посмотрю

Применение конструкции
.WithOutputParameter("ResultParameter", textDataValueType)
позволяет вызвать процедуру с исходящими параметрами.

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

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

var resultParameter = (string) storedProcedure.Parameters.FindByName("ResultParameter ").Value;

Добрый день еще раз!
Пытаюсь опять вызвать процедуру согласно инструкции (в БП в задании-сценарии)

DataValueTypeManager dataValueTypeManager = UserConnection.DataValueTypeManager;
var textDataValueType = new TextDataValueType(dataValueTypeManager);

StoredProcedure storedProcedure = new StoredProcedure(UserConnection, "tsp_test")
.WithOutputParameter("res_msg",textDataValueType) as StoredProcedure;

storedProcedure.PackageName = UserConnection.DBEngine.SystemPackageName;
storedProcedure.Execute();
return true;

Текст процедуры выглядит так:

CREATE procedure [dbo].[tsp_test]
as declare @res_msg nvarchar(250);
select @res_msg='1'
select @res_msg as res_msg

Процесс компилируется, но при запуске процесса элемент сценарий завершается с ошибкой

"System.Data.SqlClient.SqlException (0x80131904): Процедуре tsp_test не переданы параметры и аргументы"

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

Причем если вызвать процедуру без исходящего параметра
StoredProcedure storedProcedure = new StoredProcedure(UserConnection, "tsp_test")
as StoredProcedure;

то такой ошибки нет, сценарий выполняется.

Что-то не так с получением исходящего параметра процедуры?

Поняла в чем дело:
чтобы использовать конструкцию .WithOutputParameter("ResultParameter", textDataValueType) as StoredProcedure в скрипте,
необходимо в тексте самой процедуры прописывать параметр как OUTPUT:

CREATE procedure [dbo].[tsp_test]
(@res_msg nvarchar(250) OUTPUT)
as
select @res_msg='1'
select @res_msg as res_msg
return @res_msg

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

OUT | OUTPUT
Показывает, что параметр процедуры является выходным. Используйте параметры OUTPUT для возврата значений в вызвавший процедуру код.
В.Использование выходных параметров (OUTPUT)
В следующем примере создается процедура uspGetList. Эта процедура возвращает список товаров, цена на которые не превышает указанный предел. Данный пример поясняет использование нескольких инструкций SELECT и нескольких параметров OUTPUT. Параметры OUTPUT предоставляют внешней процедуре, пакету или нескольким инструкциям Transact-SQL доступ к значениям, заданным во время выполнения процедуры.

IF OBJECT_ID ( 'Production.uspGetList', 'P' ) IS NOT NULL 
    DROP PROCEDURE Production.uspGetList;
GO
CREATE PROCEDURE Production.uspGetList @Product varchar(40) 
    , @MaxPrice money 
    , @ComparePrice money OUTPUT
    , @ListPrice money OUT
AS
    SET NOCOUNT ON;
    SELECT p.[Name] AS Product, p.ListPrice AS 'List Price'
    FROM Production.Product AS p
    JOIN Production.ProductSubcategory AS s 
      ON p.ProductSubcategoryID = s.ProductSubcategoryID
    WHERE s.[Name] LIKE @Product AND p.ListPrice < @MaxPrice;
-- Populate the output variable @ListPprice.
SET @ListPrice = (SELECT MAX(p.ListPrice)
        FROM Production.Product AS p
        JOIN  Production.ProductSubcategory AS s 
          ON p.ProductSubcategoryID = s.ProductSubcategoryID
        WHERE s.[Name] LIKE @Product AND p.ListPrice < @MaxPrice);
-- Populate the output variable @compareprice.
SET @ComparePrice = @MaxPrice;
GO

Источник: https://msdn.microsoft.com/ru-ru/library/ms187926.aspx#Parameters

Спасибо, но вопрос не в этом заключался. Процедура, которую вы привели, просто возвращает два параметра выходных, а не выборку данных
А меня интересовало получение результатов выполнения процедуры в скрипте в bpmonline.
Например, процедура возвращает результат выполнения запроса select * from tbl_city
(это просто пример, выборка может быть сложнее), интересовало получение результата выполнения процедуры в bpmonline.
Но, наверное, мой вопрос уже не связан с темой бизнес-процессов - озвучу его в другой теме.
Спасибо

Добрый день, Дарья!

Для получения результата запроса из процедуры необходимо в процессе добавить в Usings:
Пространство имен: System.Data.IDataReader
Псевдоним: IDataReader

Вызов процедуры:

StoredProcedure storedProcedure = new StoredProcedure(UserConnection, "Test") as StoredProcedure;
storedProcedure.PackageName = UserConnection.DBEngine.SystemPackageName;
using (var dbExecutor = UserConnection.EnsureDBConnection()) {
            using (IDataReader dataReader = storedProcedure.ExecuteReader(dbExecutor)) {
                        while (dataReader.Read()) {
                                   var valueColumn1 = dataReader.GetValue(0);
                                   var operation = dataReader.GetColumnValue<int>("Operation");
                        }
            }
}
Показать все комментарии