Добрый день!

После добавления визирования в стандартный раздел Продаж (Opportunity), перестали приходить уведомления в Центр уведомлений коммуникационной панели. Уведомления были добавлены отметкой чек-бокса "Enable approval in section" в секции "Approval" мастера разделов. Уведомления перестали приходить в том числе и для разделов Order, Invoice, по которым они ранее приходили. Индикатор визирования в коммуникационной панели отображается,  но текст уведомления в коммуникационной панели отсутствует. Добавление схемы "OpportunityVisaNotificationProvider", записи "Terrasoft.Configuration.OpportunityVisaNotificationProvider" в таблицу "NotificationProvider" не помогло.



В консоли браузера выводится ошибка :

POST https://salesbpm.elcoin.co.uk/0/rest/VisaDataService/GetVisaEntities
[HTTP/2 400 Bad Request 84ms]
Error while sending request response status:
    400 (Bad Request)
    request url: https://salesbpm.elcoin.co.uk/0/rest/VisaDataService/GetVisaEntities
    method: POST
    request data: {"sysAdminUnitId":"3190ebaf-a3cf-461d-95f6-29115215bd39","requestOptions":{"isPageable":true,"rowCount":15}} 
The server encountered an error processing the request. The exception message is '42601: each UNION query must have the same number of columns'. See server logs for more details. The exception stack trace is:
 
at Npgsql.NpgsqlConnector.<DoReadMessage>d__157.MoveNext() 
--- End of stack trace from previous location where exception was thrown 
--- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Npgsql.NpgsqlConnector.<ReadMessage>d__156.MoveNext() 
--- End of stack trace from previous location where exception was thrown 
--- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Npgsql.NpgsqlConnector.<ReadMessage>d__156.MoveNext() --- End of stack trace from previous location where exception was thrown 
--- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Npgsql.NpgsqlConnector.<ReadExpecting>d__163`1.MoveNext() 
--- End of stack trace from previous location where exception was thrown 
--- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Npgsql.NpgsqlDataReader.<NextResult>d__32.MoveNext() 
--- End of stack trace from previous location where exception was thrown 
--- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Npgsql.NpgsqlDataReader.NextResult() at Npgsql.NpgsqlCommand.<Execute>d__71.MoveNext() --- End of stack trace from previous location where exception was thrown 
--- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Npgsql.NpgsqlCommand.<ExecuteDbDataReader>d__92.MoveNext() 
--- End of stack trace from previous location where exception was thrown 
--- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Npgsql.NpgsqlCommand.ExecuteDbDataReader(CommandBehavior behavior) at Polly.Policy.<>c__DisplayClass119_0`1.<Execute>b__0(Context ctx, CancellationToken ct) at Polly.Policy.<>c__DisplayClass129_0`1.<ExecuteInternal>b__0(Context ctx, CancellationToken ct) at Polly.Policy.<>c__DisplayClass103_0.<NoOp>b__1(Context ctx, CancellationToken ct) 
at Polly.NoOp.NoOpEngine.Implementation[TResult](Func`3 action, Context context, CancellationToken cancellationToken) at Polly.Policy.<>c.<NoOp>b__103_0(Action`2 action, Context context, CancellationToken cancellationToken) at Polly.Policy.ExecuteInternal[TResult](Func`3 action, Context context, CancellationToken cancellationToken) at Polly.Policy.Execute[TResult](Func`3 action, Context context, CancellationToken cancellationToken) at Polly.Policy.Execute[TResult](Func`1 action) at Terrasoft.Core.DB.DBExecutor.FailoverExecuteReader(DbCommand command, Func`1 func) at Terrasoft.Core.DB.DBExecutor.ExecuteCommand[TResult](Func`2 commandExecutionCallback, String sqlText, QueryParameterCollection queryParameters, CancellationToken cancellationToken) 
at Terrasoft.Core.DB.DBExecutor.InternalExecuteReader(String sqlText, QueryParameterCollection queryParameters, CommandBehavior behavior, CancellationToken cancellationToken) at Terrasoft.DB.PostgreSql.PostgreSqlExecutor.InternalExecuteReader(String sqlText, QueryParameterCollection queryParameters, CommandBehavior behavior, CancellationToken cancellationToken) at Terrasoft.Core.DB.DBExecutor.InternalExecuteReader(String sqlText, QueryParameterCollection queryParameters) at Terrasoft.Configuration.VisaHelper.GetVisaData(Select entitiesSelect) at Terrasoft.Configuration.VisaHelper.GetEntities(RequestOptions requestOptions) at SyncInvokeGetVisaEntities(Object , Object[] , Object[] ) 
at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs) at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc) at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)

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

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

Подскажите, пожалуйста, как это можно исправить?

Нравится

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

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

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



Дополнено:

В методе GetEntitiesSelect

Должно работать при таком наборе колонок (на разных версиях возможно может быть больше/меньше):

Id","CreatedOn","CreatedById","ModifiedOn","ModifiedById","ProcessListeners","Objective","VisaOwnerId","IsAllowedToDelegate","DelegatedFromId","StatusId","SetById","SetDate","IsCanceled","Comment","VisaSchemaName","Title","VisaObjectId","Date","Account","Contact","VisaSchemaTypeId","VisaTypeName","VisaSchemaCaption","SchemaName","ImageId".



В методе AddColumns

"Id","Objective","StatusId","IsCanceled","SysAdminUnitId","VisaSchemaName","VisaObjectId","Account","Contact","SchemaName","ImageId"



И 

public override void SetColumns(List<string> columns) {

            columns.Add("Id");

            columns.Add("Title");

            columns.Add("Date");

            columns.Add("Account");

            columns.Add("Contact");

            columns.Add("VisaObjectId");

            columns.Add("SchemaName");

            columns.Add("ImageId");

        }

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

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



Дополнено:

В методе GetEntitiesSelect

Должно работать при таком наборе колонок (на разных версиях возможно может быть больше/меньше):

Id","CreatedOn","CreatedById","ModifiedOn","ModifiedById","ProcessListeners","Objective","VisaOwnerId","IsAllowedToDelegate","DelegatedFromId","StatusId","SetById","SetDate","IsCanceled","Comment","VisaSchemaName","Title","VisaObjectId","Date","Account","Contact","VisaSchemaTypeId","VisaTypeName","VisaSchemaCaption","SchemaName","ImageId".



В методе AddColumns

"Id","Objective","StatusId","IsCanceled","SysAdminUnitId","VisaSchemaName","VisaObjectId","Account","Contact","SchemaName","ImageId"



И 

public override void SetColumns(List<string> columns) {

            columns.Add("Id");

            columns.Add("Title");

            columns.Add("Date");

            columns.Add("Account");

            columns.Add("Contact");

            columns.Add("VisaObjectId");

            columns.Add("SchemaName");

            columns.Add("ImageId");

        }

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

Подскажите,

1) базовый - это BaseVisaNotificationProvider? 

2) должна ли быть запись для нового раздела Opportunity в таблице "NotificationProvider" ?

3) нужно ли добавлять копии БП по подобию "OrderVisaBaseSubprocess", 

"OrderVisaBaseSubprocessOrder1",

"OrderVisaBaseProcess",

"OrderVisaBaseProcessOrder1" ?

 

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

Спасибо, починил! Отличие было в другом разделе.

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

Добрый день!

 

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

Например в инсталлмент плане есть поле Инвойс. Крестиком в выделенной записи значение этого поля можно удалять. Можно ли метод, который реагирует на нажатие крестика, переопределить? И как метод называется?

 

Спасибо! 

Нравится

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

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

Dima Avdoshin, пользователь должен иметь возможность создавать объект, видеть значение колонки Инвойс, но не иметь возможности ее менять. Когда делаю через запрет на редакт колонки, то не видят ее содержимое. Хотел добавить свою логику на крестик. 

Сергей Хоменко,

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



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



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



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



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

Пример

define("qrtqrtTestObj31ff6c52Page", ["RightUtilities"], function(RightUtilities) {
	return {
		entitySchemaName: "qrtTestObj",
		attributes: {
			"Name": {
				//dataValueType: Terrasoft.dataValueType.FLOAT,
				dependencies: [
					{
						columns: ["Name"],
						methodName: "changeName"
					}
				]
			},
		},
		modules: /**SCHEMA_MODULES*/{}/**SCHEMA_MODULES*/,
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		businessRules: /**SCHEMA_BUSINESS_RULES*/{}/**SCHEMA_BUSINESS_RULES*/,
		methods: {
			initModelColumns: function() {
				this.callParent(arguments);
				this._setColumnsDataModelName();
				this._setResourceColumns();
				this.console.log("initModelColumns");
				var self = this;
				RightUtilities.checkCanExecuteOperation({
                    operation: "qrtRulesSalesInInvoice"
                  }, function(result) {
                      self.console.log("RESULT" + result);
                      self.set("qrtSalesRules", result);
                  }, this);
			},
 
			changeName : function name() {
				if(!this.isNewMode()) {
					var isOk = this.get("qrtSalesRules")
					if(isOk) {
						this.showInformationDialog("У вас нет права на редактирование этой колонки")
						//отменяем действие
						this.onDiscardChangesClick();
					}
				}
			}
        },
      dataModels: /**SCHEMA_DATA_MODELS*/{}/**SCHEMA_DATA_MODELS*/,
		diff: /**SCHEMA_DIFF*/[
			{
				"operation": "insert",
				"name": "Name1cacb119-4c62-4e85-929a-e7a877e24794",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 0,
						"row": 0,
						"layoutName": "Header"
					},
					"bindTo": "Name"
				},
				"parentName": "Header",
				"propertyName": "items",
				"index": 0
			},
			{
				"operation": "insert",
				"name": "Description5836d8b4-157f-49bf-a943-3e6d3c28cf1e",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 0,
						"row": 1,
						"layoutName": "Header"
					},
					"bindTo": "Description"
				},
				"parentName": "Header",
				"propertyName": "items",
				"index": 1
			}
		]/**SCHEMA_DIFF*/
	};
});

 

Dima Avdoshin,

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

clearSupplyPaymentElementProducts, переопределение которой решает часть задачи без лишних маневров.

Самый простой способ использовать бизнес-правила. БП проверяете со значением булевого атрибута. А атрибуту устанавливаете значение true/false в зависимости от того, входит ли текущий пользователь в коллекцию тех, кому доступ запрещен (коллекцию можно сформировать через справочник, либо в зависимости от группы/роли, либо даже захаркодить(что не рекомендую)). Такое решение будет самым быстрым и легким, на мой взгляд 

Спасибо!

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

Добрый день!

 

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

Куда в код страницы добавить этот код, чтобы он отработал при получении сообщения?

function listener(event) { if (event.origin != 'http://javascript.ru') { // что-то прислали с неизвестного домена - проигнорируем.. return; } alert( "получено: " + event.data ); } if (window.addEventListener) { window.addEventListener("message", listener); } else { // IE8 window.attachEvent("onmessage", listener); }

Нравится

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

Добрый день!

Марат, все зависит от задачи. Вы можете разметить его как в BaseSection на init, так и в "ответе" ViewModule.aspx.

Ответ ViewModule.aspx частично формируется в конфигурации, в SectionHelper'е. Вам нужно сделать override класса ConfigurationSectionHelper. Там вы можете дописать свой JS, который отработает сразу после логона и входа в систему. Для примера обратите внимание на метод GetConfigurationScript

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

Добрый день!

На чистую коробочную версию Creatio 7.16.1.2135 SalesEnterprise_Marketing_Services было установлено приложение из маркетплейс - RabbitMQ connector for Creatio - https://marketplace.terrasoft.ru/app/rabbitmq-connector-creatio. Установка прошла без ошибок. Никаких доработок в конфигурации не выполнялось. При открытии страницы настроек коннектора следующие ошибки в консоли:

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



Разработчик на письма не отвечает. Есть какие-то идеи как исправить ошибку и заставить приложение работать?

Нравится

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

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

На скрине видно, что у Вас не заполнены параметры подключения к Rabbit. Хост, Пользователь, пароль. Эти доступы должны быть к серверу Rabbit - https://prnt.sc/1qm5ndf

Спасибо, Алексей, что откликнулись.

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

    response status: 400 (Bad Request)

    request url: http://localhost:160/0/rest/AnvRabbitConnectionService/Load

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







При этом данные верные, окно RabbitMQ в браузере открывается и нормально в авторизуется с тем же логином и паролем:





 

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

Работаю со схемами исходного кода через веб, сборку конфигурации делаю через браузер. Возможности просмотра классов библиотек через ide нет.  

По статье документации выполнена настройка nLog. После чего я создал объект логгера в схеме Исходный код как описано в туториал NLog . Объект Logger - из примера:

private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();

Получается ошибка - класса или пространства имен NLog нет , нет и пространства имен Common.Logging.NLog45. 

 

Террасофт, как у вас предполагается работать с Nlog в кодовых схемах, например в пользовательском сервисе я хотел бы писать в лог ошибку десереализации json. Примеров на схемах "исходный код" по работе с nLog в публикациях Сообщества не нашел.

Нравится

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

Для использования базового логгирования нужно подключить пространство имён global::Common.Logging, а экземпляр логгера можно получить через статический класс LogManager.

Пример кода:

namespace Terrasoft.Configuration {
	using global::Common.Logging;
 
	public class LogTest {
 
		private ILog log;
 
		public LogTest() {
			log = LogManager.GetLogger("LoggerName");
		}
 
		public void WriteError() {
			log.Error("ErrorMessage");
		}
 
	}
}

 

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

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

При отрисовке реестра детали для булевых полей отображается значение Да / Нет.

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

Прошу помощи в решении данной задачи.

 

Нравится

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

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



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

Ранее уже обсуждался подобный вопрос в посте:

https://community.terrasoft.ru/questions/ispolzovanie-checkboxov-v-deta…

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

Добрый день, видела аналогичный вопрос https://community.terrasoft.ru/questions/mobilnoe-prilozhenie-mozhno-li…

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

Нравится

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

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



Уточните, пожалуйста, интересует использование данной функциональности online или offline?





С уважением,

Сидько Елена

Оператор

Группа компаний Terrasoft

Elena Sidko,

Как онлайн, так и оффлайн

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

 

В Базовой версии нет функционала сканирование. Необходимо разработать самостоятельно используя готовую js библиотеку для сканирования. Сразу скажу, что необходимо иметь достаточно большой опыт разработки МП.

Вам необходимо сделать примерно следующее:

1. Найти подходящую js библиотеку, добавить ее в схему в конфигурации

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

3. Результат сканирования записать в необходимое поле.

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

Добрый день, коллеги! Столкнулся с такой проблемой. Создал шаблон email-сообщения. Когда я отправляю письмо в бизнес-процессе по этому шаблону, оно приходит без фона блока (в качестве фона используется картинка, а не заливка). Нашёл такую закономерность, что если картинку фона сжать до 15 КБ, то она приходит в качестве фона. Но при таком сильном сжатии (с 80 КБ до 15 КБ) сильно ухудшается качество. Картинка в base64 тега table в background. Как мне заставить Creatio отправить фон, не теряя при этом в качестве изображения?  

Нравится

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

Заикин Дмитрий, добрый день!

Фоновое изображение должно отправляться независимо от размера.

Возможно проблема в блокировках изображений\вложений\файлов со стороны почтового провайдера. 

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

Заикин Дмитрий, добрый день!

Фоновое изображение должно отправляться независимо от размера.

Возможно проблема в блокировках изображений\вложений\файлов со стороны почтового провайдера. 

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

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

Всем привет.

Версия 7.13.3.481.

 

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

 

http://localhost:7010/0/Nui/ViewModule.aspx#CardModuleV2/CommercialOfferEditPage/edit/24c9ca0d-748c-4a8b-85bb-e82dca7df06e

 

он работает через 

 

http://localhost:7010/0/Nui/ViewModule.aspx#/CommercialOfferEditPage/ed…

 

Из-за этого возникают проблемы с его открытием например из детали другого раздела или из новой вкладки. Страница открывается пустой.

Причём, если подставить в URL CardModuleV2, то всё открывается отлично.

 

Подскажите пожалуйста, как настроить нормальное открытие карточки раздела?

 

Спасибо!

Нравится

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

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

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

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

Спасибо, попробую. 

Модуль, который подставляется в ссылку определяется в таблице SysModule в поле CardModuleUId

Чтобы страница открывалась через CardModuleV2, надо вставить его Id в CardModuleUId



Id для CardModuleV2 можно получить следующим образом:



SELECT [UId]

FROM SysSchema 

WHERE [Name] = 'CardModuleV2'



Схожая проблема в обсуждении:

https://community.terrasoft.ru/questions/giperssylki-na-polzovatelskikh….

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

Здравствуйте, помогите решить задачу, пожалуйста,

На странице редактирования выведены 2 поля: Оценка (число), Оценка традиционная (Справочник).

Справочник традиционная оценка содержит колонки Название (например Удовлетворительно), Балл от (напр. 50), Балл до (напр. 69).

Как сделать так, чтобы после ввода числового значения X в поле Оценка на странице редактирования, сравнивалось значение числа по справочнику [Балл от] < X < [Балл до], и затем в справочном поле Оценка традиционная заполнялось Id найденного значения?

Хотелось бы это сделать не процессом после сохранения и закрытия карточки, а именно на странице редактирования после изменения поля.

Колонки:

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

Справочник:

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

Нравится

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

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

attributes: {
	"UsrRatingLookup": {
		dependencies: [
			{
				columns: ["UsrRating"],
				methodName: "setRatingLookup"
			}
		]
	},
},
 
methods: {
	setRatingLookup: function() {
			var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
				rootSchemaName: "UsrRatingLookup"
			});
esq.addColumn("Id");
			esq.addColumn("Name");
			var esqIdFilter = esq.createColumnFilterWithParameter(this.Terrasoft.ComparisonType.GREATER_OR_EQUAL, "UsrRatingMin", this.$UsrRating);
			esq.filters.add("esqFilter", esqIdFilter);
			var esqIdFilter2 = esq.createColumnFilterWithParameter(this.Terrasoft.ComparisonType.LESS_OR_EQUAL, "UsrRatingMax", this.$UsrRating);
			esq.filters.add("esqFilter2", esqIdFilter2);
			esq.getEntityCollection(function (result) {
				if(result.success &amp;&amp; result.collection.collection.items.length&gt;0) {
					this.set("UsrRatingLookup", {value: result.collection.collection.get(0).get("Id"), displayValue: result.collection.collection.get(0).get("Name")});
				}
			}, this);
	},
}

 

Доброе утро.

 

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

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