Привет,

Столкнулся с проблемой:

Версия: 7.13.4.638_SalesEnterprise_Marketing

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

Нравится

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

Добрый день!

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

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

Добрый день!

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

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

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

Добрый день. Поставлена задача сделать 2 таблицы в реестре раздела, так, что бы одна зависела от другой. Я изменил немного стили, добавил в блок diff еще один datagrid, переопределил некоторые методы, и задача частично решена. Отображается 2 таблицы, при выборе строки в главной таблице подгружаются данные во второстепенную. Так же реализовал просмотр карточки для второй таблицы. Но есть одна нерешенная проблема. Я хочу сделать так, что бы во второстепенной таблицы был редактируемый реестр. Что бы изменять данные в ней, не открывая карточку, и частично это уже работает.

Но есть одна проблема. При выборе строки в методе определения типа ячейки в ViewGeneratorV2, пытается определить по конфигу из основной схемы, и т.к. в основной таблице не находит конфиг ячейки второстепенной, возвращает null, и не может определить тип ячейки. Следовательно необходимо переопределить некоторые методы из ViewGeneratorV2, но этого сделать нельзя.

Посоветуйте как лучше поступить?

Нравится

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

Описываемый дизайн интерфейса с основным реестром вверху и реестром детали выбранной записи внизу использовался в версиях 3.Х и 5.Х, а в bpm'online 7.X от него отказались. Сейчас детали открывают внутри страницы редактирования, а при желании слева можно открыть вертикальный реестр раздела:

scr_list_setting_vertical_grid.png

Вы реализуете свой вариант, похожий на старые версии. Не видя всего готового кода, развёрнутого в системе, сложно дать точечную рекомендацию. Если стандартно в каком-то разделе есть похожий механизм, посмотрите в нём. В первую очередь, начните с раздела «Планирование», где самый нестандартный подход к реестру:

scr_edited_plan.png 

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

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

Нравится

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

Добрый день!

Да, заходите в системную настройку, указываете пункт "Разрешить по операции". Системную операцию используете существующую, либо создаете новую.

Добрый день!

Да, заходите в системную настройку, указываете пункт "Разрешить по операции". Системную операцию используете существующую, либо создаете новую.

Сидоров Александр В.,

в 7.12 такого нет, наверно это в более новой версии

Ещё один повод обновиться сразу до актуальной.

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

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

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

Вот потому и думаю, и так обновления проходят не без проблем, а так ещё добавятся

В таком случае стоит обновляться. В версии 7.13 права уже есть.

У нас сейчас 7.12.4, будет стимул проставить на прод. Спасибо

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

Коллеги,

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

Можно ли так сделать? Если "да", то как это можно организовать?

Нравится

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

Добрый день!

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

Спасибо!

Нравится

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

Здравствуйте! На Маркетплейс есть решение которое определяет запущенные процессы по объекту - https://marketplace.terrasoft.ru/app/processes-log-view-bpmonline

Здравствуйте! На Маркетплейс есть решение которое определяет запущенные процессы по объекту - https://marketplace.terrasoft.ru/app/processes-log-view-bpmonline

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

Ошибка при запуске "полнота наполнения данными" вручную процесса. В академии написано что необходимо запустить бизнес-процесс “Обновить полноту профиля”, но это приводит в ошибке. Подскажите как правильно произвести пересчет этого показателя? 

Нравится

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

Если бы тут привели текст выводимого на экран или в логи при запуске БП сообщения, гадать о причинах было бы намного легче: фаза Луны, погода на Марсе...wink

А так можно только посоветовать воспользоваться инструментами Visual Studio и Management Studio: отладить функцию RecalculateAll в схеме BaseCompletenessService, которую запускает этот БП и запустить с теми же параметрами хранимку tsp_CompletenessRenew в базе, которую функция запускает.

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

если запускать "Обновить полноту профиля"

 

Oracle.DataAccess.Client.OracleException ORA-00936: missing expression
ORA-06512: at "BPM.tspkg_Completeness", line 113
ORA-06512: at line 2    at Oracle.DataAccess.Client.OracleException.HandleErrorHelper(Int32 errCode, OracleConnection conn, IntPtr opsErrCtx, OpoSqlValCtx* pOpoSqlValCtx, Object src, String procedure, Boolean bCheck)
   at Oracle.DataAccess.Client.OracleCommand.ExecuteNonQuery()
   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.DB.Oracle.OracleExecutor.FailoverExecute[TResult](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.Execute(String sqlText, QueryParameterCollection queryParameters)
   at Terrasoft.Core.DB.StoredProcedure.Execute()
   at Terrasoft.Configuration.BaseCompletenessService.RecalculateAll()
   at Terrasoft.Core.Process.CompletenessRenew.ScriptTask1Execute(ProcessExecutingContext context)
   at Terrasoft.Core.Process.ProcessFlowElement.Execute(ProcessExecutingContext context)

Если запускать "Запустить обновление полноты профиля"

System.NullReferenceException: Object reference not set to an instance of an object.
   at Terrasoft.Configuration.BaseCompletenessService.get_AppConnection()
   at Terrasoft.Configuration.BaseCompletenessService.RecalculateAllByCompleteness(Guid completenessId)
   at Terrasoft.Configuration.BaseCompletenessService.RecalculateAll()
   at Terrasoft.Core.Process.CompletenessRenew.ScriptTask1Execute(ProcessExecutingContext context)
   at Terrasoft.Core.Process.ProcessFlowElement.Execute(ProcessExecutingContext context)

 

Значит ещё и используется Oracle... Нужно смотреть, что находится в пакете spkg_Completeness во второй строке и во входящей в него хранимке tsp_CompletenessRenew в 113 строке и рядом. Были ли в них доработки?

Есть ли замещения схемы BaseCompletenessService? Если есть, попробуйте удалить, скомпилироваться, повторить запуск процесса.

Изменений и замещений нет. Содержание хранимой процедуры

create or replace PACKAGE BODY "tspkg_Completeness"
AS
	FUNCTION "fn_Is_Number" (stringValue IN VARCHAR2)
	RETURN INT
	IS
		new_Number NUMBER;
	BEGIN
		new_Number := TO_NUMBER(stringValue);
	RETURN 1;
	EXCEPTION
		WHEN VALUE_ERROR THEN
			RETURN 0;
	END;
 
	PROCEDURE "tsp_CompletenessRenew" (CompletenessId VARCHAR2)
	IS
	BEGIN
		DECLARE 
			EntitySchemaName VARCHAR2(50);
			TypeColumn VARCHAR2(50);
			TypeValue VARCHAR2(38);
			ResultColumn VARCHAR2(50);
			sqlcmd VARCHAR2(30000);
			createTableSql VARCHAR2(30000);
			whereSql VARCHAR2(30000);
			updateSql VARCHAR2(30000);
			fromSelectSql VARCHAR2(30000);
			c_id VARCHAR2(38);
			c_column_name VARCHAR2(500);
			c_detail_name VARCHAR2(500);
			c_detail_column VARCHAR2(500);
			c_master_column VARCHAR2(500);
			c_is_column VARCHAR2(1);
			c_is_detail VARCHAR2(1);
			c_percentage INT;
			c_type_column VARCHAR2(50);
			c_type_value VARCHAR2(38);
			typed_detail_name VARCHAR2(500);
			attributes_count INT;
 
			CURSOR attributes_cursor IS 
				SELECT 
					cp."Id",
					cp."ColumnName",
					cp."DetailEntityName",
					cp."DetailColumn",
					cp."MasterColumn",
					cp."IsColumn",
					cp."IsDetail",
					cp."Percentage",
					cp."TypeColumn",
					cp."TypeValue"
				FROM "CompletenessParameter" cp
				WHERE cp."CompletenessId" = (
					SELECT "Id" FROM "Completeness" c WHERE c."Id" = CompletenessId);
		BEGIN
			attributes_count := 0;
			SELECT "EntitySchemaName", "TypeColumnName", "TypeColumnValue", "ResultColumnName"
				INTO EntitySchemaName, TypeColumn, TypeValue, ResultColumn
				FROM "Completeness" WHERE "Id" = CompletenessId;
			createTableSql := 'CREATE TABLE "CalcCompleteness" AS SELECT  "Id", "'||ResultColumn||'", SUM(';
			fromSelectSql := 'FROM "' || entitySchemaName || '" a ';
			whereSql := ' WHERE ';
			OPEN attributes_cursor;
			LOOP
				FETCH attributes_cursor into 
					c_id,
					c_column_name,
					c_detail_name,
					c_detail_column,
					c_master_column,
					c_is_column,
					c_is_detail,
					c_percentage,
					c_type_column,
					c_type_value;
				EXIT WHEN attributes_cursor%notfound;
				attributes_count := attributes_count + 1;
				IF c_is_column = '1' THEN
 
					createTableSql := createTableSql || ' CASE WHEN ("' || c_column_name || '" IS NULL) OR (LENGTH("' || c_column_name || '") = 0)';
					createTableSql := createTableSql || ' OR ("tspkg_Completeness"."fn_Is_Number"("' || c_column_name || '") = 1 AND TO_NUMBER("' || c_column_name || '") = 0) THEN 0 ELSE ' || c_percentage || ' END +';
				ELSE
					typed_detail_name := c_detail_name;
					IF (c_type_column IS NOT NULL OR c_type_column <> '') AND (c_type_value IS NOT NULL OR c_type_value <> '') THEN
						typed_detail_name := c_detail_name || TO_CHAR(attributes_count); 
					END IF;
 
					createTableSql := createTableSql || ' CASE WHEN NVL(' || typed_detail_name || '."' || c_detail_name || '", 0) = 0 THEN 0 ELSE ' || c_percentage || ' END +';
 
					fromSelectSql := fromSelectSql || ', (SELECT COUNT("'|| c_detail_name ||'"."'||c_detail_column||'") "'|| c_detail_name ||'", "'||c_detail_column||'" FROM "'||c_detail_name||'"';
					IF (c_type_column IS NOT NULL OR c_type_column <> '') AND (c_type_value IS NOT NULL OR c_type_value <> '') THEN
						fromSelectSql := fromSelectSql || ' WHERE "' || c_detail_name ||'"."'||c_type_column||'" = '''||c_type_value||'''';
					END IF;
					fromSelectSql := fromSelectSql ||' GROUP BY "'||c_detail_column||'") ' || typed_detail_name;
 
					whereSql := whereSql || 'a."Id" = '||typed_detail_name||'."'||c_detail_column||'"(+) AND ';
				END IF;
			END LOOP;
			CLOSE attributes_cursor;
 
			IF attributes_count <> 0 THEN
				createTableSql := SUBSTR(createTableSql, 0, LENGTH(createTableSql) - 2);
				createTableSql := createTableSql || ') AS "NewCompleteness"';
				whereSql := SUBSTR(whereSql, 0, LENGTH(whereSql) - 6);
				IF (TypeColumn IS NOT NULL OR TypeColumn <> '') 
					AND (TypeValue IS NOT NULL OR TypeValue <> '') THEN
 
					whereSql := whereSql || ' AND a."' || TypeColumn || '" = '''||TypeValue||'''';
				END IF;
				createTableSql := createTableSql || fromSelectSql || whereSql;
				createTableSql := createTableSql || ' GROUP BY a."Id", a."'||ResultColumn||'"';
				EXECUTE IMMEDIATE createTableSql;
				sqlcmd := 'CREATE UNIQUE INDEX calcCompleteness_id_ix ON "CalcCompleteness" ("Id")';
				EXECUTE IMMEDIATE sqlcmd;
				updateSql := 'UPDATE 
					(SELECT 
						t1."Id", 
						t2."Id",
						t1."'||ResultColumn||'" "Completeness1", 
						t2."NewCompleteness" "NewCompleteness"
					FROM 
						"'||EntitySchemaName||'" t1, 
						"CalcCompleteness" t2 WHERE t1."Id" = t2."Id" AND t1."'||ResultColumn||'" <> t2."NewCompleteness") SET "Completeness1" = "NewCompleteness"';
				EXECUTE IMMEDIATE  updateSql;
				sqlcmd := 'DROP TABLE "CalcCompleteness"';
				EXECUTE IMMEDIATE  sqlcmd;
			ELSE
				sqlcmd := 'UPDATE "'||EntitySchemaName||'" SET "'||ResultColumn||'" = 0';
				EXECUTE IMMEDIATE  sqlcmd;
			END IF;
		END;
	END; 
END "tspkg_Completeness";

 

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

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

если имеете введу вносил ли я изменения - нет. Настройки производил по инструкции

Речь о самодельных деталях в этом разделе, если они есть.

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

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

В хранимке  идёт в цикле перебор деталей раздела. Возможно, с одной из деталей что-то не то.

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

Добрый день!

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

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

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

Нравится

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

Этот метод используется только в схеме OrderPageV2 пакета Order:

/**
* Validates payment status and change if valid.
* @protected
* @param {Function} callback The callback function.
* @param {Object} scope Environment object callback function.
*/
validatePaymentStatus: function(callback, scope) {
	if (this.validate()) {
		var parameters = {
			columnNames: ["PaymentStatus"],
			callback: this.handleColumnRightsAvailability.bind(this, callback, scope)
		};
		this.checkColumnsEditRight.call(this, parameters);
	} else {
		callback.call(scope || this);
	}
},
 
/**
* Handles column rights availability.
* @private
* @param {Function} callback The callback function.
* @param {Object} scope Environment object callback function.
* @param {Object} columnRights Rights of column.
*/
handleColumnRightsAvailability: function(callback, scope, columnRights) {
	if (columnRights.PaymentStatus) {
		this.changePaymentStatus(callback, scope || this);
	} else {
		callback.call(scope || this);
	}
},

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

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

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

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

Нравится

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

Поля расширяют через CSS, если оно оказывается шире экрана, включается прокрутка. Возможно, и с контейнером реестра так получится.

А вообще, горизонтальная прокрутка — зло и не нужна.

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

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

Нравится

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

Добрый день!

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

Добрый день!

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

Сидоров Александр В.,

не помогает, на Supervisor проверил

Александр Тыра,

Supervisor всегда обладает всеми правами. Ограничить у него их нельзя

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

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

Допустим руководитель входит в раздел, у него есть группа по его филиалу, и он видит только свой филиал так как может просматривать только эту группу.

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

Нравится

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

Александр Тыра,

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

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

Уточните, какой нюанс мешает настроить доступ через права доступа?

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

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

Кроме жирного курсива можно ещё КАПСОМ писать, чтобы заметнее было.wink

Александр, Вы описываете бизнес-логику системы. Всю видимость или невидимость конкретных записей конкретному пользователю задаётся раздачей прав на записи. Их можно выдавать вручную или запрограммировать логику выдачи при помощи бизнес-процесса. Например, при добавлении лида в группу (добавление записи в таблицу LeadInFolder) добавлять или убирать право на чтение или запись на этот лид нужной группе пользователей.

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

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

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

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

вот и я не вижу, жалко

Александр Тыра,

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

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

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

в правах доступа вижу сколько настройки доступа только по колонке "кто создал" и "кому дано право". Если имеете введу " доступ по объектам в конфигураторе.

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

Конфигуратор тут не нужен, права на конкретную запись настраиваются по действию в карточке.

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

но это руками нужно править

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

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

​​​​​​это заказчик). Хотят что бы сразу все

Если хотят, чтобы видели сразу все, пусть добавят доступ группе «Все пользователи». Если хотят ограничивать, нужно выдавать другие права доступа на записи. Их можно выдавать либо вручную из интерфейса, либо различными способами программно.

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