Коллеги, добрый день
Есть потребность привязать старт Бизнес-Процесса к окончанию процедуры Импорта данных
С учетом того, что импорт может производиться в разные разделы (Контакты/Контрагенты/...) — нужно понимать, какой именно объект служил конечной точкой

Вопрос:
Подскажите, пожалуйста, можно ли на уровне Бизнес-процесса получить информацию о том, куда был совершен импорт файла? Есть ли в БД таблица, содержащая поле, в котором бы хранилось подобное значение?

Нравится

0 комментариев
Показать все комментарии
Работаю с FastReport (Создание провайдера данных отчета) и возник вопрос. 
Как найти Guid entitySchemaUId? 
В примере который есть (Знаменательные события контакта(пример)) указано 
private readonly Guid _contactEntitySchemaUId = new Guid("41af89e9-750b-4ebb-8cac-ff39b64841e");

Когда, создаю по примеру, то требуется поменять Guid, то откуда беру (из объекта к прим.: (0/ClientApp/#/EntitySchemaDesigner/41af89e9-750b-4ebb-8cac-ff39b64841ec) не правильно, т.к. при попытке печати отчета выходит ошибка неполадки сервера

Нравится

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

SQL:

select UId
from SysSchema
where Name = 'Contact' and ExtendParent = 0

C#:

UserConnection.EntitySchemaManager.GetInstanceByName("Contact").UId

 

Добрый день.

 

Получить UId схемы можно запросом из таблицы:

select UId
from SysSchema
where Caption = N'<Заголовок схемы>'

 

SQL:

select UId
from SysSchema
where Name = 'Contact' and ExtendParent = 0

C#:

UserConnection.EntitySchemaManager.GetInstanceByName("Contact").UId

 

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

не совсем правильно, так как ваш запрос вернет несколько строк, для каждой замещенной схемы. А нужно взять UId самого базового объекта.

Владислав Литвинчук,
привет , а что будет самым базовым объектом для Lead , я перебирал буквально каждый , но не с одним фаст репорт не заработал, просто выдает ошибку загрузки и все, хотя в примере из академии на объекте контакта все норм

Где ExtendParent = 0, как в моем запросе выше.

Владислав Литвинчук,

проставила вместо 0 false, иначе выдавал ошибку 
Он выдал две записи, какую все же из них следует выбрать?

Анастасия Демидова,

0 - MS, false - Postgre скорее всего.
Данный запрос не может выдать 2 записи. В системе сожет быть только 1 схема объекта без наследования.
Можно скриншот запроса и результата выборки?

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

Как получить и обработать результирующие параметры при вызове БП из кода?

В версии 7.17.1 обещали получение параметров из интерпретируемого процесса, но примеров как и что нету. Запуск я проводил с помощью класса FlowEngine и метода RunProcess.
В sdk по классу flowengine ничего не добавилось.

Нравится

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

FlowEngine - устаревший класс и он не рекомендуется к использованию.

Для работы с процессами лучше использовать экземпляр IProcessExecutor который можно получить из UserConnection. Пример запуска процесса с получением одного параметра:

string processName = "UsrCustomProcess";
string paramName = "UserProcessParameter";
IProcessExecutor processExecutor = UserConnection.ProcessEngine.ProcessExecutor;
// Необходимо указание типа параметра
int result = processExecutor.Execute<int>(processName, paramName);

Пример запуска с получением нескольких параметров:

string processName = "UsrCustomProcess";
string[] paramNames = { "UserProcessParameter0", "UserProcessParameter1" };
IProcessExecutor processExecutor = UserConnection.ProcessEngine.ProcessExecutor;
// Второй аргумент - список входящих параметров
ProcessDescriptor processDescriptor = processExecutor.Execute(processName, new Dictionary<string, string>(), paramNames);
// Получение параметров
IReadOnlyDictionary<string, object> result = processDescriptor.ResultParameterValues;

 

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

Привет,

При попытке компиляции функционала получил ошибку, видимую в веб интерфейсе конфигуратора, а именно: Не удалось привести тип объекта "Newtonsoft.Json.Linq.JObject" к типу "Newtonsoft.Json.Linq.JArray".

Где я могу посмотреть более подробную информацию? Хотя бы в какой строке возникло данное исключение.

В логах искал, "C:\Windows\Temp\BPMonline\BPMOnline" - там нет ничего ,если искать, например Newtonsoft или JObject или JArray

Возможно логгирование можно включить? 

Нравится

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

Ошибка скорее всего из-за того, что хоть пакет и накатывается на 7.15, но разрабатывался он на более новой версии (7.16.3+).

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

У Вас именно версия 7.15? Было такое в 7.16.3, устранено в 7.16.4.

Проблема возникает из-за бага версии 7.16.3, в метаданных схемы некорректно генерируется встроенный бизнес-процесс объекта из-за чего возникает ошибка при парсинге.
Как обходное решение Вы можете добавить любой элемент во встроенный процесс объекта, сохранить его, после чего удалить элемент и снова сохранить, однако я рекомендую обновить приложение до более новой версии для полного устранения проблемы.

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

Версия 7.15.2.501

Возможно, тоже при обновлении устранится. Или поможет обходной способ из сообщения выше.

Ошибка скорее всего из-за того, что хоть пакет и накатывается на 7.15, но разрабатывался он на более новой версии (7.16.3+).

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

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

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

При создании письма без шаблона посылается нормально, а шаблоны сразу добавляют отступы

Нравится

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

Добрый день.

 

Мне в поддержке ответили следующее: начиная с версии 7.15.2 используется новый дизайнер контента и функционал регулирования расположения шаблона внутри дизайнера отсутствует. 
Шаблон располагается по центру по умолчанию. Ширина по умолчанию задана 600.

Для решения проблемы, увеличьте ширину шаблона. 
Нажмите на шестеренку в правом верхнем углу и выберите максимальную ширину страницы. (максимально допустимая 1300px).

 

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

Измените положение, похоже что у вас по центру стоит.

Добрый день.

 

Мне в поддержке ответили следующее: начиная с версии 7.15.2 используется новый дизайнер контента и функционал регулирования расположения шаблона внутри дизайнера отсутствует. 
Шаблон располагается по центру по умолчанию. Ширина по умолчанию задана 600.

Для решения проблемы, увеличьте ширину шаблона. 
Нажмите на шестеренку в правом верхнем углу и выберите максимальную ширину страницы. (максимально допустимая 1300px).

 

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

Полозюков Евгений Петрович,

это что за версия?

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

С 7.12 по текущую версию такое точно есть.

Как интересно - есть два типа шаблонов. Но непонятно, как управлять, какой тип создать

 

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

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

Признак ConfigType – это тип шаблона, но этот признак – следствие того, что конфиг шаблона такого типа, его изменение ни к чему не приведёт.

Для того, чтобы открылся старый дизайнер, TemplateConfig у шаблона должен быть старого образца, этого можно достичь либо копированием старого шаблона, либо update в базе данных поля TemplateConfig на конфиг старого образца.

 

Уже заведена идея о необходимости выравнивания в новых шаблонах.

 

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

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

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

Это делается просто, устанавливая права на записи.

Однако, если эта запись используется в поле другого объекта (например, Контрагент в Продажах), то в поле отображается название контрагента, несмотря на то, что сам контрагент пользователю недоступен.

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

Нравится

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

Залезть в loadGridData или prepareResponseCollection и чистить значения коллекции перед отрисовкой.

Залезть в loadGridData или prepareResponseCollection и чистить значения коллекции перед отрисовкой.

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

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

 

Такая ситуация:

 

к полю привязал атрибут, к которому подвязал вызов функции checkEpicId. Функция обращается к сервису, который в свою очередь обращается к стороннему сервису и возвращает строку для валидации. Получив ответ, функция анализирует респонс и устанавливает для колонки invalidMessage i isValid. На странице внизу колонки появляется установленный invalidMessage, но карточка все равно сохраняется с таким invalidMessage. Добавил ф-ю валидатор isInJiraValidator, но тоже не помогает.

 

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

 

код:

setValidationConfig: function() {
                this.callParent(arguments);
                this.addColumnValidator("UsrCoEpicId", this.isInJiraValidator);
            },
isInJiraValidator: function(value) {
                var invalidMessage = "";
                return {
                    invalidMessage: invalidMessage
                };
            },
 checkEpicId: function() {
                  var newEpicIdTitle = "";
                  var epicId = this.get("UsrCoEpicId");
                  var invalidMessage = "";
                  var isValid = false;
                ServiceHelper.callService(
                    "UsrJiraApi",
                    "getEpicId",
                    function(response) {
                          var res = response.getEpicIdResult;
                          var epicResult = response.substring(10, 11);
                          if(epicResult == "t") {
                              newEpicIdTitle = response.substring(response.indexOf("summary") + 10, response.indexOf("assetId") - 3);
                              console.log("Length after assetId: " + response.substring(response.indexOf("assetId")).length);
                              if(response.substring(response.indexOf("assetId")).length > 15) {
                                  var jiraAssetId = response.substring(response.indexOf("assetId") + 10, response.indexOf("assetId") + 46);
                                  console.log("Asset in CRM: " + this.get("UsrAssetTypeGeneral").value);
                                  console.log("Asset in Jira: " + jiraAssetId);
                                  if(this.get("UsrAssetTypeGeneral") && (this.get("UsrAssetTypeGeneral").value == jiraAssetId)) {
                                    invalidMessage = "";
                                      isValid = true;
                                   } else {
                                    invalidMessage = "Asset Type in Jira is not the same as in CRM for current Epic Id."
                                          + " Please set correct values or refer to administrator.";
                                      isValid = false;
                                  }
                            } else {
                                invalidMessage = "";
                                  isValid = true;
                                  this.showMessage("Asset Type in Jira is not set for current Epic Id. Validation is not awailable.");
                            }
                              this.validationInfo.set("UsrCoEpicId",{invalidMessage: invalidMessage, isValid: isValid});
                              this.set("UsrJiraEpicName", newEpicIdTitle);
                        } else {
                              invalidMessage = epicId + " - there is no such Epic Id in Jira. Please enter correct Epic Id."
                                  + " In case the epic Id in Jira has not been yet created - please do it now";
                              isValid = false;
                              this.validationInfo.set("UsrCoEpicId",{invalidMessage: invalidMessage, isValid: isValid});
                              this.set("UsrJiraEpicName", newEpicIdTitle);
                        }
                    },epicId,
                this);
            },

Нравится

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

в ф-и валидаторе не получилось реализовать получение ответа от внешнего сервиса из-за ассинхронности.

Сергей, возможно, есть смысл пересмотреть логику и получать нужную информацию из Jira в момент открытия карточки или изменения поля UsrAssetTypeGeneral, а затем получать список подходящих для выбора значений справочника getEpicId и фильтровать справочное поле по нему? Тогда и валидация не потребеутся.

Александр, спасибо! Ваш совет помог.

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

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

В карточке:

Что за настройка? Как это исправить?

Нравится

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

Виталий, с версии 7.16 поменялся механизм работы с почтой, появился сервис синхронизации Exchange Listener.

Вам нужно заполнить настройку ExchangeListenerServiceUri согласно инструкции.

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

Для реализации логики в событийном слове после вызова base.onSaved() в entity отсутствуют значения, которые устанавливаются в тех самых процессах объекта Saved.

Пока сделали дополнительный Select для получения обновленного entity и Update.

 

Эта верная логика или можно получить обновленный entity (полученный после отработки base.onSaved()) на событийном слое без вызова Select?

Нравится

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

Полозюков Евгений Петрович пишет:
Если это синхронный вариант, не вижу причины зачем его делать таким образом, а не как обычно через событийный подпроцесс

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

Добрый вечер.

Получить обновленный entity можно таким образом:

public override void OnSaved(object sender, EntityAfterEventArgs e)
{
   base.OnSaved(sender, e);
   Entity entity = (Entity)sender;
   var userConnection = entity.UserConnection;
  // реализуем нужную логику
 }

Ещё посмотрите вот эту статью на Академии: https://academy.terrasoft.ua/docs/developer/back-end_development/entity…

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

именно так и делали по этой статье. Простой пример, который должен был показать значение Code
 

[EntityEventListener(SchemaName = "Account")] 
public class UsrAccountEntityEventListener : BaseEntityEventListener
 {
  public override void OnSaved(object sender, EntityAfterEventArgs e) {
    base.OnSaved(sender, e);
 
    var entity = (Entity) sender;
    var userConnection = entity.UserConnection;
 
    string accountCode = entity.GetTypedColumnValue&lt;string&gt;("Code");
 
    throw new Exception(entity.Schema.Name + " " + accountCode);

Однако значение Code, которое генерируется в процессе объекта onSaved было пустое.

Добавили Select, получили значение.
 

public override void OnSaved(object sender, EntityAfterEventArgs e) {
 base.OnSaved(sender, e);
 
 var entity = (Entity) sender;
 var userConnection = entity.UserConnection;
 Guid id = entity.PrimaryColumnValue;
 string schemaName = entity.Schema.Name;
 
 Select select = new Select(userConnection).Top(1)
  .Column("Code")
  .From(schemaName)
  .Where("Id").IsEqual(Column.Parameter(id)) as Select;
 string accountCode = select.ExecuteScalar<string>();

 

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

А зачем вам асинхронный вариант?

Обычный событийный подпроцесс нормально работает.

В ScriptTask получаем Entity.GetTypedColumnValue<string>("Code")

 

Полозюков Евгений Петрович пишет:
А зачем вам асинхронный вариант?

в каком месте у нас асинхронный вариант? 
Как раз в процессе получается асинхронно - иногда раньше, иногда позже процесса из родительского объекта

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

Мне показалось что это асинхронный вариант.

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

Полозюков Евгений Петрович,

потому что событийные подпроцессы как раз работают асинхронно

Скорее всего, из-за того, что в процессе значение для поля 'Code' устанавливается на onSaved, оно не попадает в параметр sender в обработчике в событийном слое.

 

Хотя это может быть и ошибкой, так как в документации написано, что механизм событийного слоя Entity срабатывает после выполнения событийных подпроцессов объекта.

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

 

Как вариант решения, можно либо устаналивать значение для поля 'Code' не в обработчике onSaved, а в onSaving в подпроцессе объекта, либо реализовать всю логику в одном месте или в подпроцессе, или в событийном слое.

Полозюков Евгений Петрович пишет:
Если это синхронный вариант, не вижу причины зачем его делать таким образом, а не как обычно через событийный подпроцесс

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

Алла Савельева пишет:
Как вариант решения, можно либо устаналивать значение для поля 'Code' не в обработчике onSaved, а в onSaving в подпроцессе объекта, либо реализовать всю логику в одном месте или в подпроцессе, или в событийном слое.

А есть идеи, как "выпилить" из базового функционала генерацию Code, оставив при этом остальные обработки процесса (синхронизация средств связи и прочее)?

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

Создайте свое поле и пишите к нему свою логику.

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

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

Алла Савельева пишет:
Очень часто сталкиваюсь с ситуациями, когда понимаешь, что проще было реализовать свое, чем использовать базовый функционал

Это всё понятно. Иногда незамещаемый базовый функционал доставляет больше проблем, чем его гипотетическое отсутствие.

Workaround мы нашли, но хотелось бы понять, как было задумано в системе

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

Здравствуйте,
мы питаемся в Бизнес процесс добавить подпроцесс, и когда передает только значение Лида, все ок,
но в подпроцессе у нас есть параметр, текстовый, и на него вылетает ошибка:

"Значение не может быть неопределенным. Имя параметра: format"
Пробовали и заполнять этот параметр значением по умолчанию в подпроцессе, и передавать значение с процесса, 
если он присутствует всегда одна и та же ошибка.

Версия: 7.15.4.3055

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

Нравится

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

Уточните, у Вас параметр назвается format или Name? Или это два разных параметра?

Здравствуйте, параметр называется - Name, с названием format у меня ничего нет.

Уверены, что дело именно в этом подпроцессе? Если запускать его из другого процесса, тоже такая ошибка?

Если переименовать Name как-то иначе, то тоже?

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

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

А в логи системы (стандартно в текстовом файле Error.log на веб-сервере) при этом что-то падает? В консоли браузера нет дополнительной информации в момент ошибки?

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