Вопрос

Хочу в процесса объекта на событии Saving (Перед сохранением) в событийном под процессе.

Сверять значение

Entity.GetTypedOldColumnValue<Guid>("Calendar")==Guid.Empty;

И останавливать сохранение. Подскажите что нужно сделать чтобы приостановить сохранение?

У меня такой же вопрос

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

Посмотрите этот пост, в котором обсуждается подобная задача.

Так же можно воспользоваться событийным слоем Entity

Алла Савельева пишет:

Посмотрите этот пост, в котором обсуждается подобная задача.

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

Entity.GetTypedOldColumnValue<Guid>("Calendar")==Guid.Empty

А в чём суть такой проверки? Так, если поле в какой-то момент стало пустое, больше никогда не сможете его заполнить и сохранить запись средствами ESQ.

Зверев Александр пишет:

Entity.GetTypedOldColumnValue<Guid>("Calendar")==Guid.Empty

А в чём суть такой проверки? Так, если поле в какой-то момент стало пустое, больше никогда не сможете его заполнить и сохранить запись средствами ESQ.

Поле календарь обязательно, и используется в расчетах.

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

Тогда зачем проверять GetTypedOldColumnValue? Оно же возвращает старое значение, а не нынешнее. Просто проверку обязательности для поля можно включить в дизайнере объекта.

Или же настроить значение по умолчанию и писать туда основной используемый календарь.

Казанцев Андрей Юрьевич пишет:
Поле календарь обязательно, и используется в расчетах.При заполнении всех полей в реестре детали и нажатия на кнопку закрыть страницы. Это значение сохраняется пустым. А по нему идет расчет. 

Вашу задачу, действительно, можно решить одним из вариантов, предложенными выше Александром.

Если все-таки хотите решить эту задачу через сравнение старого и нового значения, то лучше это делать на клиентском, а не на серверном уровне. Посмотрите метод asyncValidate.

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

Доброго времени суток!

Необходимо запустить N подпроцессов из основного процесса и каким-то образом ожидать выполнения всех подпроцессов.

Буду благодарен любым идеям.

UPD-1. Изначально не известно сколько будет подпроцессов, поэтому такого рода схема не подойдет

У меня такой же вопрос

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

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

что то вроде такого -http://prntscr.com/ocm1ol

Вот наглядный пример, создал 3 БП, в них добавил разные таймеры и посмотрим как идет обработка в главном БП
http://prntscr.com/ocmaqq - Главный
http://prntscr.com/ocmaxg - 1 мин задержки
http://prntscr.com/ocmb6t - 2 мин задержки
http://prntscr.com/ocmbg8 - 3 мин задержки

Запускаем основной и смотрим диаграму:
http://prntscr.com/ocmc05
http://prntscr.com/ocmc9u
http://prntscr.com/ocmck4 - завершился (диаграма выполнения основного без изменения - http://prntscr.com/ocmcso)
http://prntscr.com/ocmda0

Нигрескул Алексей,

Обновил описание вопроса

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

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

А где создавать это поле? И как сделать обработчик сигнала?

В каком-то объекте, подходящем по логике, с которым по смыслу связаны эти процессы. Обработчик — сигнал на изменение поля в объекте.

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

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

Уменьшать и считывать старое значение можно в том же запросе.

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

Гарантируется ли при использовании этого запроса правильный подсчет одновременно завершающихся подпроцессов?

Этот способ не является стандартным. Как такое делать штатно, описал выше для фиксированного числа процессов Алексей. Тут же все гарантии будет давать разработчик, то есть Вы. По идее, если всё в одном SQL-запросе, то мешать не будет.

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

Зверев Александр пишет:Уменьшать и считывать старое значение можно в том же запросе.

Через такой запрос не генерится сигнал 

Действительно, в таком случае используйте не Update, а ESQ. Синхронизацию в этом случае нужно предусмотреть самостоятельно. Либо же менять при помощи Update, а в следующем шаге менять другое поле по ESQ или посылать сигнал иным образом.

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

Так вышло что пришлось быстро в пакете Customer создавать бизнес процессы что бы подправить ошибки тех что в пакетах кинфирурации. И сейчас на этих процессах весят задачи. Как можно эти процессы убрать из пакета Customer? Если просто изменить процессы в которых были ошибки (версии которые замещали процессы в пакете Customer) и удалить временные - то задачи созданные версией процесса в пакете Customer так же удалятся с ним

У меня такой же вопрос

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

Добрый день,

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

Добрый день,

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

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

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

У меня такой же вопрос

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

Эмм... также как и тут создаём замещающий объект.

Только потом идём в родителя смотрим, где находится конкретный скрипт таск

Далее в процессе замещённого объекта справа ищем такой же лайн-сет и открываем скрипт-таск (дабл кликом), редактируем, сохраняем.

Варфоломеев Данила,

Попробовал, как Вы предлагаете. Но безуспешно. Система вовсе игнорирует изменения, сделанные из замещающего объекта. Даже код с синтаксическими ошибками успешно проходит публикацию. Хотя, изменения сохраняются. Что я делаю не так?

Бершеда Д. Н. пишет:
Хотя, изменения сохраняются. Что я делаю не так?

Согласен, я написал фигню) Изменить стандартные реализации скорее всего нельзя.

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

Подскажите, как в Процессе изменить Бизнес-Правило ограничивающее доступ на редактирование поля? Какой элемент процесса нужно использовать?

У меня такой же вопрос

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

имеется в виду бизнес-процесс ?

Севостьянов Илья Сергеевич,

Да.

я не уверен, что такая возможность имеется, именно в виде "изменить бизнес-правило", но можно создать бизнес-правила выполнение которых зависит от значения атрибута модели, и например "скрытое поле" в целевом объекте, в бизнес-процессе устанавливать значение в это поле, а в целевой схеме предусмотреть логику (н/п в onEntityInitialized) которая опираясь на значение вышеуказанного поля будет устанавливать значение в атрибут модели.
Итоговый результат, ИМХО - это тот кейс, который вы хотите реализовать, насколько я понял.

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

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

У меня такой же вопрос

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

Сергей, такая возможность есть.
Пример можно посмотреть на академии в этой статье.

Спасибо Наталия. Буду разбираться.

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

Версия
7.9.1.3284
Нужно добавить в БП звонок-элемент чтобы его привязать к активностям и другим объектам.

У меня такой же вопрос

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

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

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

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

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

Вы можете настроить процесс:
1. Стартовый сигнал по изменению записи в звонке, где Активность заполнена.
2. Читать данные в активности, где Id = Пункт 1. Активность.
3. Раздать права доступа на активность, где Id = Пункт 2. Id
4. Открыть страницу редактирования активности, где Id = Пункт 2. Id

Хорошо, это сделаю, но как настроить видимость кнопок звонка и эмейла в миникарточке активности, они создаются динамически. (две кнопки ля контакта и две для контрагента)

Добрый день!

Не могли бы Вы прикрепить скриншот Вашей миникарточки и код создания данных кнопок?


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

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

Логика данной миникарточки находится в UIv2.ActivityMiniPage. Кнопки добавляются при ее создании(методы init и onEntityInitialized). Логика отображения кнопок находится в UIv2.MiniPageEntityConnectionsUtils и NUI.EmailExtendedMenu и работает именно так как Вы описали - при создании миникарточки формируется EntitySchemaQuery запрос в базу данных, и если у данного контака(контрагента) заполнена колонка телефон(e-mail) кнопка будет добавлена. Если таких данных нет - не будет и кнопки.

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

Всем добрый день!

Появилась трудность с реализацией запуска процесса "Блокировка карты" по нажатию на кнопку.
Для страницы "Карты" создал замещающую страницу BankCardPagev2. Добавил в diff создание кнопки "CardBlock", прописал метод ProcCardBlock. Создал процесс UsrCardBlock, в котором создал параметр ProcParamCardId.
Может я что забыл сделать, можете подсказать, плиз.

2) Правильно я понимаю, что для реализации запуска процесса по кнопке, сам процесс достаточно начинать с простого начального события?

P.S. Кнопка на странице появилась, при нажатии на нее выдает ошибку: "ProcessModuleUtilities is not defined"

define('BankCardPageV2', ['BankCardPageV2Resources', 'GeneralDetails'],
function(resources, GeneralDetails) {
        return {
                entitySchemaName: 'BankCard',
                details: /**SCHEMA_DETAILS*/{
        "BankAccountInBankCardDetailV2": {
                "schemaName": "BankAccountInBankCardDetailV2",
                "entitySchemaName": "BankCardBankAccount",
                "filter": {
                        "masterColumn": "Id",
                        "detailColumn": "BankCard"
                }
        }
}/**SCHEMA_DETAILS*/,
                diff: /**SCHEMA_DIFF*/[
        {
                "operation": "merge",
                "name": "StartDate",
                "values": {
                        "layout": {
                                "column": 0,
                                "row": 0,
                                "colSpan": 12,
                                "rowSpan": 1
                        }
                }
        },
        {
                "operation": "merge",
                "name": "EndDate",
                "values": {
                        "layout": {
                                "column": 0,
                                "row": 1,
                                "colSpan": 12,
                                "rowSpan": 1
                        }
                }
        },
        {
                "operation": "merge",
                "name": "BankCardStatus",
                "values": {
                        "layout": {
                                "column": 12,
                                "row": 0,
                                "colSpan": 12,
                                "rowSpan": 1
                        }
                }
        },
        {
                "operation": "insert",
                "name": "UsrBlockType",
                "values": {
                        "layout": {
                                "column": 0,
                                "row": 2,
                                "colSpan": 12,
                                "rowSpan": 1
                        },
                        "bindTo": "UsrBlockType",
                        "caption": {
                                "bindTo": "Resources.Strings.BlockTypeCaption"
                        },
                        "textSize": 0,
                        "contentType": 3,
                        "labelConfig": {
                                "visible": true
                        },
                        "enabled": true
                },
                "parentName": "StatusGroupGridLayout",
                "propertyName": "items",
                "index": 3
        },
        {
                "operation": "insert",
                "name": "UsrBlockReason",
                "values": {
                        "layout": {
                                "column": 12,
                                "row": 2,
                                "colSpan": 12,
                                "rowSpan": 1
                        },
                        "bindTo": "UsrBlockReason",
                        "caption": {
                                "bindTo": "Resources.Strings.BlockReasonCaption"
                        },
                        "textSize": 0,
                        "contentType": 3,
                        "labelConfig": {
                                "visible": true
                        },
                        "enabled": true
                },
                "parentName": "StatusGroupGridLayout",
                "propertyName": "items",
                "index": 4
        },
        {
                "operation": "insert",
                //"parentName": "LeftContainer",
                "name": "NewButton",
                "values": {
                                "itemType": Terrasoft.ViewItemType.BUTTON,
                                "style": Terrasoft.controls.ButtonEnums.style.RED,
                                "caption": "CardBlock",
                                "click": {"bindTo": "ProcCardBlock"}
                }
        }
]/**SCHEMA_DIFF*/,
                attributes: {},
                methods: {
                                ProcCardBlock: function() {
                                        var activeRowId = this.get("ActiveRow");
                                        var args = {
                                                sysProcessName: "UsrCardBlock",
                                                parameters :{
                                                        ProcParamCardID: activeRowId
                                                }
                                        };
                                ProcessModuleUtilities.runProcess(args.sysProcessName, args.parameters, this);
                                }
                        },
                rules: {},
                userCode: {}
        };
});

У меня такой же вопрос

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

Добрый день.
Вам нужно в первых двух строчка :

define('BankCardPageV2', ['BankCardPageV2Resources', 'GeneralDetails'],
function(resources, GeneralDetails) {

дописать ProcessModuleUtilities , это примерно выглядить должно так:

define('BankCardPageV2', ['BankCardPageV2Resources', 'GeneralDetails', 'ProcessModuleUtilities '],
function(resources, GeneralDetails, ProcessModuleUtilities ) {

Роман, спасибо!
Теперь кнопка реагирует на нажатие :)
Но появляется ошибка

"При выполнении запроса возникла ошибка
статус ответа: 404 (Not Found)
url запроса: http://172.26.20.18:81/0/ServiceModel/ProcessEngineService.svc/UsrCardB…
метод: POST
данные запроса: {}"

Исходя из ошибки, предполагаю, что у меня косяк с процессом. Сейчас процесс сделал самый простой : начальное событие простое - открыть страницу редактирования - завершающее событие.
В методе ProcCardBlock объявлен параметр ProcParamCardId, такой же параметр создал в процессе и в странице редактирования передаю ID записи значение этого параметра.
Можете подсказать, что не так или чего не сделал, чтобы верно передать в процесс ID записи и он стартанул.

С уважением,
Дмитрий

В урл видно же что параметр не передался, точнее вместо айди передалось андефайнед:
?ProcParamCardID=undefined

Т.к. вы:
var activeRowId = this.get("ActiveRow");

пытаетесь получить в карточке, в карточке нет атрибута ActiveRow, если вам нужно Id записи карточки, то так и пишите

var activeRowId = this.get("Id");

Всем большое спасибо.

Процесс запустили :)

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

Возникли трудности с переносом кнопки в блок кнопок "Сохранить", "Отменить", "Действия".

Как я понимаю, выбор контейнера в поле "parentName" зависит от типа страницы (новая или редактируемая).
Если использовать LeftContaner, то кнопка отлично уходит в верхний левый угол на новых записях.
А если использовать CombinedModeActionButtonsCardLeftContainer то кнопка распологается снизу слева на странице как новой так и редактируемой страницы.
Можете подсказать, что нужно изменить в коде, чтобы кнопка появились слева вверху вместе с кнопками "Сохранить", "Отменить", "Действия".

"operation": "insert",
		"parentName": "CombinedModeActionButtonsCardRightContainer",
		"propertyName" :"items",
		"name": "NewButton",
		"values": {
			"itemType": Terrasoft.ViewItemType.BUTTON,
			"style": "red",
			"caption": {"bindTo": "Resources.Strings.CardBlockCapture"},
			"click": {"bindTo": "ProcCardBlock"},
			"layout": {
				"column": 1,
				"row": 6,
				"colSpan": 1
Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

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

У меня такой же вопрос

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

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

Используйте для объединения потоков перед созданиям счета элемент "И".

Но я так понимаю "И" ждет выполнения всех веток.
Мне нужно - Если у меня хотя бы одна из них выполнится - мне нужно создать один счет, но не больше.

Ну тогда используйте "Исключающее ИЛИ" - здесь все логично:smile:

Не могу понять никак. Вот У меня два из трех процессов пришли к "Исключающее ИЛИ". И каким условием мне сделать чтобы дальше процес пошел только раз к счету?

Добавьте в процесс два параметра..
1. Требутся сделать счет
2. Счет сделан
И их анализ в начале секции, создающей счет :)

Добавьте в процесс два параметра..
1. Требутся сделать счет
2. Счет сделан
И их анализ в начале секции, создающей счет :)

Добавьте в процесс два параметра..
1. Требутся сделать счет
2. Счет сделан
И их анализ в начале секции, создающей счет :)

ой.. трижды отправилось :cry:
Модератор, почистите пжлста :)

Я думал над этим вариантов, но эти ветки приходят в точку одновременно, поэтому условие проверки их всех пропустит на создание счета...

Тогда параметр "счет сделан" меняем на параметр "Счетов сделано" и смотрим, чтоб значение было меньше 2 :)

Спасибо. Уже разобрался!

Кстати, да.. формула почему-то в цикле второй раз не отрабатывает... Тоже сталкивался.
Помогло переписать это условие в C# скрипте...

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

Добрый день!

Для того, чтобы процесс автоматически запускался раз в N минут, необходимо в процесс поместить элемент Сценарий вида:

string schedulerJobGroupName = "MyProcessGroupMyEmail1";//- Любое имя
string jobProcessName = "UsrProcess"; //- Название процесса
string schedulerJobName = "MyJobNameMyEmail1"; //- Любое имя
int startOffset = 3600; // интервал в секундах
AppScheduler.RemoveJob(schedulerJobName, schedulerJobGroupName);
var job = AppScheduler.CreateProcessJob(schedulerJobName, schedulerJobGroupName, jobProcessName, UserConnection.Workspace.Name, UserConnection.CurrentUser.Name);
var trigger = new SimpleTriggerImpl(schedulerJobName + "Trigger", schedulerJobGroupName, DateTime.UtcNow.AddSeconds(startOffset));
AppScheduler.Instance.ScheduleJob(job, trigger);
return true;

Это работает.

Скажите, пожалуйста, а можно ли сделать так, чтобы он запускался только в определенные часы
(например, с 8.00 до 20.00)

т.е. как можно здесь применить такую формулу ?
Если 20:00 - текущее время

У меня такой же вопрос

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

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

Пример использования планировщика в указанном интервале.

string schedulerJobGroupName = "ScheduleTest";
string jobProcessName = "UsrScheduleTest";
string schedulerJobName = "ScheduleTestJob";
TimeSpan start = TimeSpan.Parse("11:31");
TimeSpan end = TimeSpan.Parse("11:46");
TimeSpan currentTime = DateTime.Now.TimeOfDay;

if ((currentTime > start) && (currentTime < end))
{
int startOffset = 30;
AppScheduler.RemoveJob(schedulerJobName, schedulerJobGroupName);
var job = AppScheduler.CreateProcessJob(schedulerJobName, schedulerJobGroupName, jobProcessName, UserConnection.Workspace.Name, UserConnection.CurrentUser.Name);
var trigger = new SimpleTriggerImpl(schedulerJobName + "Trigger", schedulerJobGroupName, DateTime.UtcNow.AddSeconds(startOffset));
AppScheduler.Instance.ScheduleJob(job, trigger);
} else {
int startOffset = 12;
AppScheduler.RemoveJob(schedulerJobName, schedulerJobGroupName);
var job = AppScheduler.CreateProcessJob(schedulerJobName, schedulerJobGroupName, jobProcessName, UserConnection.Workspace.Name, UserConnection.CurrentUser.Name);
var trigger = new SimpleTriggerImpl(schedulerJobName + "Trigger", schedulerJobGroupName, DateTime.UtcNow.AddHours(startOffset));
AppScheduler.Instance.ScheduleJob(job, trigger);
}
return true;

Спасибо

а можно как-то посмотреть, что записано в планировщике? какие задания когда стоят на автозапуске?

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

Вы можете проверить существующие тригера выполнив запрос в БД:
select * from QRTZ_TRIGGERS
select * from QRTZ_SIMPLE_TRIGGERS

Войдите или зарегистрируйтесь, чтобы комментировать