Коллеги, приветствую.

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

Я хочу добавить элемент "Задание- сценарий", который будет читать поступления платежей по долгам и далее определять логику ветвления.

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

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

Был бы весьма признателен за информацию.

Спасибо.

--
С уважением, Алексей Быков.

Нравится

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

Коллеги, приветствую.

В дизайнере бизнес- процессов есть действие "Звонок". Как запланировать его на определенную дату?
Посмотрел в настройках, ничего похожего не нашел:

Был бы весьма признателен за информацию.

Спасибо.

--
С уважением, Алексей Быков.

Нравится

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

Добрый день,

Можно с помощью планировщика запланировать время выполнения самого процесса.
http://www.community.terrasoft.ru/forum/topic/12917
Можно запланировать время выполнения элемента с помощью Таймера.
Нужно понимать, что в этих случаях необходимо отталкиваться от какого-то времени или события.

Можно добавить активность с типом звонок с помощью элемента Добавление данных – указать дату начала активности.

Здравствуйте, Олег! Отлично, спасибо большое, буду пробовать.

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

Добрый день, возможно ли в ПФ Word подставить контакт текущего пользователя?

Нравится

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

Коллеги, приветствую.

Есть некоторый элемент- действие "Чтение данных", который считывает записи из таблицы и помещает в некоторую результирующую коллекцию ResultEntityCollection.

Как обратиться к этой коллекции из кода C# в действии "Задание- сценарий"?

Был бы весьма признателен за информацию.

Спасибо.

--
С уважением, Алексей Быков.

Нравится

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

Алексей,

В новом движке процессов работать можно только с параметрами процесса, либо напрямую с параметрами элементов, на которые настроен маппинг.
Пример решения задачи во вложении.
scripttaskmapping.txt

Олег, спасибо большое за ответ! Посмотрю сегодня.

Олег, не могли бы Вы выложить пример в UTF-8? Был бы весьма признателен.

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

Согласно этому сайту, мой коллега хотел написать следующее:
1. Создать параметр процесса типа Строка - TestParam.
2. В значение параметра указать [#Read data 1.First item of resulting collection#].GetTypedColumnValue("Name")
3. В элементе Задание-сценарий работать с параметром.
var contactFullName = Get("TestParam");

Отлично, спасибо большое за ответ!

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

Коллеги, приветствую.

Есть некоторый элемент- действие "Чтение данных", который считывает записи из таблицы
и помещает в некоторую результирующую коллекцию ResultEntityCollection.

Далее я определяю параметр AggregateCollection, в котором будет сохраняться данная коллекция и через который я буду обращаться к ней из кода C#:

Значение данного параметра:

[#Чтение данных из таблицы контракты.Результирующая коллекция#]

В элементе "Задание- сценарий" я пытаюсь получить данный параметр:

var entityCollection = Get("AggregateCollection");
foreach (var entity in entityCollection) {
        Console.WriteLine(entity);
}

Однако на выходе ничего нет. Конфигурация компилируется без ошибок.

Как правильно обратиться к коллекции объектов EntityCollection?

Был бы весьма признателен за информацию.

Спасибо.

--
С уважением, Алексей Быков.

Нравится

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

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

Коллекция не сериализуется в БД. По этой причине она пустая. Какую задачу Вы хотите решить?

Алексей, спасибо за Ваш ответ! Не сериализуется - в том смысле, что должна или не должна? Чекбокс "Сериализировать значение" проставлен по- умолчанию для элемента "Чтение данных". В нем я по определенному фильтру считываю записи. Когда данный элемент добавляется в дизайнер БП, для него создаются ряд параметров, в т.ч. ResultEntityCollection. Все параметры - не редактируемые. Чтобы обратиться к этой коллекции ResultEntityCollection из C# я создаю в параметрах процесса параметр AggregateCollection с типом "Коллекция объектов (EntityCollection)". Может, коллекцию нужно привязать к моему параметру через формулу?

Для параметра AggregateCollection проставил чекбокс "Сериализировать значение", ничего не изменилось..

Собственно, когда я говорил "на выходе ничего нет" я имел в виду, конечно, что entityCollection == null

Переехали в эту тему

Да, пожалуй - все же интересно, как передать коллекцию в сценарий.
Этот кейс я решил с помощью элементов бизнес-процессов, без действий- сценариев.

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

Добрый день! у меня проблема с программой, я создаю файл dataset для своего fast report, но при добавлении полей справочника программа закрывается, Microsoft Script Debugger у меня установлен, данную ошибку не отслеживает, клиентская часть работает вроде нормально, помогите решить данную проблему.

Нравится

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

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

Не понятно, что, как и куда вы добавляете. Постарайтесь, пожалуйста, более детально описать проблему (желательно со скриншотами).

Программа закрывается с каким-то сообщением? С каким?

Получается ли запустить тот отчет, который Вы модифицируете, из TSClient?

я пытаюсь сделать свой fastreport с нуля, но при добавлении полей справочников в dataset, программа вылетает, в чем моя ошибка?

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

К сожалению, по предоставленным Вами сервисам ничего конкретного сказать нельзя.

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

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

1) Вы добавляете поля в тот датасет, который находится в архиве?
2) Какие именно поля Вы добавлете, что указываете в качестве источника?
3) Возникает ли эта ошибка, если Вы пытаетесь добавить такое же поле в другой датасет или только в этот?

Эта информация нужна, чтобы установить причину ошибки.

1) нет, у свой созданый датасет
2) добавляю поле customer, типу справочника, указиваю в нем источник ds_Account, дальше сохраняю, пробую вернуться и выбивает ошибку
3) да, возникает, уже все перепробовал

1) Сервис в архиве тоже назвается ds_TestReport и содержит те же поля. Он у меня открывается без ошибок.
2) Для анализа проблемы выложите ещё сервис отчета fr_TestReport (также, если, как Вы утвержаете, select query и dataset отличаются от тех, которые находятся в предыдущем комментарии в архиве, добавьте и их).

Также рекоммендую обратиться в службу поддержки и запросить последние бинарные файлы для обновления текущей версии Terrasoft.

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

Здравствуйте, изучил тему по ссылке. В частности последний пост.
Возник ряд вопросов:
- Как правильно использовать dbExecutor для избежания утечки памяти?
- В каких именно случаях нужно пользоваться указанным в теме подходом?
- Всегда ли нужно оборачивать методы Execute() и ExecuteScalar() классов Select, Insert, Update в using, если нет, то в каких случаях это не обязательно?

Используемые версии приложения - от 7.4 и выше

Нравится

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

продублирую пост из ссылки в данную тему:

"Венжик Игорь" написал:Часто возникает ситуация когда необходимо сделать специфичечкий запрос к БД, который невозможно или сложно воспроизвести с помощью бизнес-сущностей. Например запросы к таблицам прав доступа, к системным таблицам. (Не законченная статья...)

В таких случая необходимо строить кастомные запросы:

Select select =
        new Select(UserConnection)
                .Column("Id")
                .Column("SysSchemaId")
                .Column("Name")
                .Column("SysSchemaManagerName")
                .Column("SysSchemaFolderId")
                .Column("MetaDataModifiedOn")
        .From("VwSysSchemaInSolution")
        .Where("SysSolutionId").IsEqual(new QueryParameter("solutionId", userConnection.Solution.Id))
                .And("SysSchemaId").In(schemas)
                .And("SysSchemaStateInSolution").IsNotEqual(Column.Const((int)StoringObjectState.Deleted))
                .And().OpenBlock("LockedById").IsNull()
                        .Or("LockedById").IsEqual(new QueryParameter("currentUserId", userConnection.CurrentUser.Id))
                .CloseBlock()
                as Select;
Для выполнения запросов к БД в нашей системе есть специальный объект DBExecutor. Экземпляр которого содержится в каждом UserConnection-е. То есть одному пользователю всегда доступен только один экземпляр DBExecutor-а, и пользователь не может сам создавать новые экземпляры.
Что бы получить экземпляр DBExecutor-а необходимо вызвать метод UserConnection.EnsureDBConnection().
using (var dbExecutor = UserConnection.EnsureDBConnection()) {

}
Для вызова всегда необходимо использовать конструкцию using!

Давайте раcсмотрим несколько вариантов работы

Допустим нам необходимо выполнить простой запрос:

Select select =
        new Select(UserConnection)
                .Column("Name")
        .From("Contact")
        .Where("City").IsEqual(Column.Parameter("Киев"))

Получение значения из первой строки, первого столбца выборки

Есть два способа

var name = select.ExecuteScalar();
или
string name;
using (var dbExecutor = UserConnection.EnsureDBConnection()) {
        name = select.ExecuteScalar(dbExecutor);
}
Оба способа вернут один и тот же результат. Если вы выполняете одиночный запрос тогда используйте первый вариант, он является оберткой над вторым. Второй вариант, с передачей dbExecutor-а, будет полезен если выполнять несколько запросов к БД в рамках одной транзакции.

Получение списка значений:

List names = new List();
using (var dbExecutor = UserConnection.EnsureDBConnection()) {
        using (var reader = select.ExecuteReader(dbExecutor)) {
                while(reader.Read()) {
                        int columnOrdinal = reader.GetOrdinal("Name");
                        names.Add(reader.GetString(columnOrdinal));
                }
        }
}

Выполнение запроса в рамках транзакции:

Оба запроса в базу будут выполнены в рамках транзакции и в случае свала транзакция откатится.

List names = new List();
using (var dbExecutor = UserConnection.EnsureDBConnection()) {

>>      dbExecutor.StartTransaction();
       
        using (var reader = select.ExecuteReader(dbExecutor)) {
                while(reader.Read()) {
                        int columnOrdinal = reader.GetOrdinal("Name");
                        names.Add(reader.GetString(columnOrdinal));
                }
        }
        insert.Execute(dbExecutor);

>>      dbExecutor.CommitTransaction();

}
Транзакция начинается вызовом метода dbExecutor.StartTransaction и заканчивается вызовом CommitTransaction или RollbackTransaction. В случае когда выполнение вышло за область видимости блока using и CommitTransaction не был вызван, происходит автоматический откат транзакции. Таким образом нет необходимости оборачивать транзакцию в try/catch блок, т.к. если был свал во время выполнения транзакция автоматически откатится.

Внимание! В текущей реализации даже если не передавать dbExecutor в метод Execute(), все равно запрос будет выполнен в текущей транзакции, если такая существует. Но для избежания сложностей в будущем, всегда при выполнении нескольких запросов в рамках транзакций - всегда передавайте dbExecutor в методы Execute, ExecuteReader, ExecuteScalar.

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

Методы Execute() и ExecuteScalar() классов Select, Insert, Update в using оборачивать не нужно.
Для Select-ов ExecuteScalar или Execute, который принимает анонимный метод - также не стоит оборачивать в using.
Для Select-а, который использует конструкцию List names необходимо использовать Using:

List names = new List();
using (var dbExecutor = UserConnection.EnsureDBConnection()) {
using (var reader = select.ExecuteReader(dbExecutor)) {
while(reader.Read()) {
int columnOrdinal = reader.GetOrdinal("Name");
names.Add(reader.GetString(columnOrdinal));
}
}
}

Добрый день! Давно и сильно интересует вопрос, каким образом обернуть в транзакцию событийный процесс объекта при сохранении/удалении? Для гарантированной согласованности данных в разных сущностях, когда изменения в одном объекте влекут изменения в другом связанном.

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

Коллеги, приветствую.

Столкнулся с некоторыми трудностями чтения из базы данных с помощью объекта DBExecutor.

Есть простой кастомный запрос:

 

var userConnection = Get("UserConnection");
Guid addedRecordId = Get("addedRecordId");

var selectQuery = new Select(userConnection)
        .Column("UsrName")
        .From("UsrDebt").As("ud")
        .Where("UD", "Id")
                .IsEqual(Column.Parameter(addedRecordId));

 

Читаю значение UsrName (пример - Помогите с запросом):

 

using (var dbExecutor = userConnection.EnsureDBConnection()) {
        var name = selectQuery.ExecuteScalar(dbExecutor); // строка 46
}

 

Получаю ошибку компиляции -

Если читаю набор данных, как показано в статье Использование EntitySchemaQuery для построения запросов к базе данных:

 

var userConnection = Get("UserConnection");
Guid addedRecordId = Get("addedRecordId");

var selectQuery =
        new Select(userConnection)
        .Column("UsrName")
        .From("UsrDebt").As("ud")
        .Where("UD", "Id")
                .IsEqual(Column.Parameter(addedRecordId));

// Выполнение запроса к базе данных и получение результирующего набора данных.
using (DBExecutor dbExecutor = userConnection.EnsureDBConnection())
{
    using (IDataReader reader = selectQuery.ExecuteReader(dbExecutor)) // строка 48
    {
        while (reader.Read())
        {
            // Обработка результатов запроса.
        }
    }
}

 

Получаю такую ошибку:

Как я могу получить значения из базы данных с помощью объекта DBExecutor?

Был бы весьма признателен за информацию.

Спасибо.

--
С уважением, Алексей Быков.

Нравится

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

Добавил преобразование к типу Select, теперь все Ок.

var selectQuery = new Select(userConnection)
    	.Column("UsrName")
    	.From("UsrDebt").As("ud")
    	.Where("UD", "Id")
	.IsEqual(Column.Parameter(addedRecordId)) as Select;
Показать все комментарии

Коллеги, приветствую.

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

F6F4725A-C7C6-4AA2-BE50-E4878ACB7D4B

Я выполняю простой запрос из MS SQL Server Management Studio -

SELECT
        UsrInDebtId
FROM
        UsrDebt
WHERE
        Id='F6F4725A-C7C6-4AA2-BE50-E4878ACB7D4B';

Получаю какой- то результат.

Аналогично из кода C#

...
myConnection.Open();
SqlCommand myCommand = new SqlCommand("...", myConnection);
SqlDataReader myReader = myCommand.ExecuteReader();
while (myReader.Read()) {
   ...
}
...    

Уникальный идентификатор я сохраняю в параметре addedRecordId -

Guid addedRecordId = Get("addedRecordId");

Далее я хочу использовать класс Select из пространства имен Terrasoft.Core.DB -

var userConnection = Get("UserConnection");
Select select = (Select)new Select(userConnection)
            .Column("UserInDebtId")
            .From("UsrDebt").As("UD")
            .Where("UD", "Id")
            .IsEqual(addedRecordId); // строка 42

Получаю ошибки компиляции -

Как я могу использовать Guid в условии IsEqual?

Был бы весьма признателен за информацию.

Спасибо.

--
С уважением, Алексей Быков.

Нравится

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

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

Например:

string str = "F6F4725A-C7C6-4AA2-BE50-E4878ACB7D4B";
Guid guid = new Guid(str);

А затем уже:

...
.IsEqual(guid);

Хотя и не совсем ясно, что бы это могло дать...

Алексей,

В этом случае можно решить задачу двумя способами:

Вариант 1.
.IsEqual(addedRecordId.ToString());
Вариант 2.
.IsEqual(Column.Parameter(addedRecordId));

Второй вариант более корректный.

Здравствуйте, Олег! Большое спасибо за ответ, попробую сегодня.

В обоих случаях получаю такую ошибку компиляции:

Cannot implicity convert type 'Terrasoft.Core.DB.Query' to 'Terrasoft.Core.DB.Select'. An explicit
conversion exists (are you missing a cast?)

Нужно видеть всю картину, трудно так определить где зарыт камень.
Напишите в техническую поддержку.

Олег, спасибо.

Помогло использование переменной с неявным типом:

var selectQuery = 
	new Select(userConnection) ...
Показать все комментарии

Коллеги, приветствую.

Есть некоторый простой бизнес- процесс, инициируемый событием- сигналом "Добавление записи в таблицу".

Например:

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

Как это сделать? Насколько я понимаю, нужно добавить параметр, но как записать в него Guid той записи, которая добавляется?

Был бы весьма признателен за информацию.

Спасибо.

--
С уважением, Алексей Быков.

Нравится

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

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

У стартового сигнала есть параметр "Идентификатор записи" (RecordId). Создайте параметр процесса NewID с типом "Уникальный идентификатор". Используйте элемент "Формула" для передачи параметра StartSignal.RecordId в созданный Вами параметр NewID.
Используйте в задании-сценарии следующий код, чтобы получить значение, которое хранится в параметре NewID:

Id = Get<Guid>("NewID")

В итоге в параметре элемента "Задание-сценарий" будет установлено Id стартового сигнала.

Здравствуйте, Алексей! Спасибо большое за ответ, сейчас попробую сделать это.

Алексей, спасибо еще раз, все верно.

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