В продолжение данного топика 

Правило дедубликации только по телефону не работает. Более того, методом научного тыка было обнаружено следующее:

1) Мы создали правило поиска по телефону и ещё одному полю UsrDedub (по аналогии правило поиска по названию и телефону).

2) Сделали значение UsrDedub = 1 в нескольких контрагентах (около 20). В лиде UsrDedub также = 1. Правило отработало корректно.

3) Сделали значение UsrDedub = 1 для всех контрагентов (около 7 500). Правило работать перестало.

4) Изменили параметр @offsetLimit в SQL запросе tsp_FindAccountSimilarRecords с 200 на 7500. Правило вновь стало работать.

Отсюда мы сделали вывод - правило поиска по телефону отрабатывает только по коллекции контрагентов, которые уже отобраны каким либо правилом поиска дублей.

Копаем дальше, но может кто-то может подсказать:

1) Насколько изменение @offsetLimit может быть критичным для быстродействия системы. Изменение до 10 000 визуально никаки систему не загрузили.

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

3) Либо если он работает в паре с другим правилом - в первую очередь проводить поиск именно по телефону?

Нравится

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

Оказалось, что именно низкий @offsetLimit не позволяет правилу поиска похожих контрагентов по телефону отрабатывать корректно индивидуально. Чем чревато увеличение этого значения - пока не знаю.

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

1. Если будет слишком большое количество записей, то вполне возможен отвал запроса по timeout.

2, 3.  Для того, чтобы правило поиска похожих контрагентов в лидах работало отдельно, необходимо в хранимой процедуре tsp_FindAccountSimilarRecords изменить блок "IF @execStmt IS NOT NULL..."  на:

               SET @detailsSelectQuery = N'SELECT TOP '+ CAST(@offsetLimit as NVARCHAR) +

                ' ' + @queryColumnName + CHAR(10) + 

                'FROM ' + CHAR(10) + @schemaName + CHAR(10) +

                'WITH (NOLOCK) ' + CHAR(10) +

                'WHERE 1=1 ';

                IF @execStmt IS NOT NULL

                BEGIN

                    SET @detailsSelectQuery = 

                    @detailsSelectQuery + CHAR(10) + 'AND' + CHAR(10) + @queryColumnName + CHAR(10) + ' IN ('    + @execStmt + ')';

                END

                IF @equalQueryConditions IS NOT NULL

                BEGIN

                    SET @detailsSelectQuery = @detailsSelectQuery + CHAR(10) + 

                    @equalQueryConditions;

                END

                IF @inQueryConditions IS NOT NULL

                BEGIN

                    SET @detailsSelectQuery = @detailsSelectQuery + CHAR(10) + @inQueryConditions;

                END

                IF @detailsSelectQuery IS NOT NULL

                BEGIN

                    INSERT INTO @resultIdsTable

                    EXEC sp_executesql @detailsSelectQuery;

                END

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

Привет, подскажите, пожалуйста, в 7.11.3 в свойствах объекта появился флаг «Наследовать права доступа от объекта», как он должен работать? В документации не нашел.

Например, если я открываю контрагент для которого у меня права только на чтение и пытаюсь добавить запись на детали «Адреса», то адрес сохраняется без проблем. Но при попытке отредактировать этот же адрес, выдается ошибка, что у меня не хватает прав. Правильно я понимаю, что флаг «Наследовать права доступа от объекта» просто копирует правила из родительского объекта, но не проверяет права на родительскую запись?

Нравится

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

Здравствуйте, Сергей!

Суть изменений в том, что есть детали которые не администрируются по записям вообще и настраивать правила достаточно трудозатратно и не оправданно сложно. На текущий момент в версиях 7.11.3 данная фича по умолчанию выключена. Т.е. вне зависимости от заполненности поля поведение по проверке прав не изменится. 

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



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

Коллеги, подскажите, пожалуйста, где можно прочитать о данной функциональности? Не могу найти в Системе данный чекбокс.

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

Спасибо!!!!!

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

Кейс следующий: сделать правило дедубликации в разделе лиды по похожим контрагентам с проверкой ТОЛЬКО по телефону. Базовое правило не подходит, поскольку проверяет по названию И телефону.

Добавил правило в DuplicatesRule, добавил процедуру поиска с помощью SQL запроса (см. AccountPhoneRuleUsr). Ничего не выходит. Что интересно, если убрать из базового правила (phoneAndAccountNameRule) упоминание поиска по названию, то он тоже перестаёт отрабатывать в принципе. Такое ощущение, что где-то прописано, что поиск по телефону работает только в паре с каким-то совпадением.

Кто-нибудь сталкивался с данной задачкой?

IF(OBJECT_ID('dbo.tsp_FindAccountSimilarRecords','P')) IS NOT NULL
	DROP PROCEDURE dbo.tsp_FindAccountSimilarRecords
GO
 
CREATE PROCEDURE tsp_FindAccountSimilarRecords (@primaryColumnValue uniqueidentifier, @rawXMLConfig nvarchar(MAX), @offsetLimit int = 200)
AS 
 
 
DECLARE @parsedConfig TABLE (
	SchemaName nvarchar(128),
	ParentShemaName nvarchar(128) NULL,
	ColumnName nvarchar(128),
	ColumnValue nvarchar(4000),
	ColumnValueTypeId nvarchar(128)
 );
 
DECLARE @accountRulesConfig TABLE (
	RuleId uniqueidentifier, 
	SchemaName sysname,
	ParentSchemaName sysname NULL,
	ColumnName sysname, 
	NormalizeFnPattern nvarchar(4000),
	CleanDataSchemaName sysname NULL);
 
DECLARE @xmlBody xml;
 
DECLARE @webAndAccountNameRule uniqueidentifier = 'd3607fd4-8303-40ae-b66e-000000000013'	,
		@phoneAndAccountNameRule uniqueidentifier = 'd3607fd4-8303-40ae-b66e-000000000014'	,
		@cityAndAccountNameRule uniqueidentifier = 'd3607fd4-8303-40ae-b66e-000000000015'	,
		@countryAndAccountNameRule uniqueidentifier = 'd3607fd4-8303-40ae-b66e-000000000016'	,
		@AccountNameRule uniqueidentifier = 'd3607fd4-8303-40ae-b66e-000000000017'	,
		@AccountPhoneRuleUsr uniqueidentifier = '778e768d-3941-4461-8954-59702c1f1fab'	,
		@AccountInnRule uniqueidentifier = '1470da34-31ae-4da5-b6c8-9410751133a4'	;
 
DECLARE @leadSchemaUId uniqueidentifier = '41AF89E9-750B-4EBB-8CAC-FF39B64841EC' ;
 
DECLARE @accountSchemaName sysname = 'Account',
		@accountCleanDataSchemaName sysname = 'VwAccountCleanDataValues',
		@accountCommunicationSchemaName sysname = 'AccountCommunication',
		@accountCommunicationCleanDataSchemaName sysname = 'VwAccountCommunicationCleanDataValues',
		@accountAddressSchemaName sysname = 'AccountAddress';
 
DECLARE @accountNameColumn sysname = 'Name',
		@accountInnColumn sysname = 'UsrINN',
		@accountCommunicationColumn sysname = 'Number',
		@accountCommunicationPhoneColumn sysname = 'SearchNumber',
		@accountCountryColumn sysname = 'CountryId',
		@accountCityColumn sysname = 'CityId',
		@communicationTypeIdColumn sysname = 'CommunicationTypeId';
 
DECLARE @resultIdsTable TABLE (Id uniqueidentifier);
 
DECLARE @phoneCommunicationTypeTable TABLE (Id uniqueidentifier);
 
DECLARE @preStmtValues TABLE (
	ColumnName sysname NOT NULL,
	ColumnValue nvarchar (4000) NULL,
	SchemaName sysname NOT NULL,
	ColumnValueTypeId NVARCHAR(128)
);
 
 
DECLARE @emailNormalizePattern nvarchar(50) = N'0-9a-zа-я@_.',
		@nameNormalizePattern nvarchar(50) = N'0-9a-zа-я',
		@normalizedFnSelectStmt nvarchar(250),
		@innNormalizePattern nvarchar(12) = N'0-9',
		@normalizedFnValueStmt nvarchar(250);
 
DECLARE @execStmt nvarchar(MAX),
		@baseNormalizeFn sysname = 'dbo.fn_NormalizeString',
		@phoneNormalizeFn sysname = 'dbo.fn_ExtractDigitLimitFromNumber',
		@webNormalizeFn sysname = 'dbo.fn_ExtractDomainFromUrl';
 
DECLARE @ruleId uniqueidentifier,
		@countDetailValues int = 0;
 
DECLARE @inQueryConditions nvarchar(MAX),
		@equalQueryConditions nvarchar(MAX),
		@schemaName sysname,
		@queryColumnName nvarchar(128);
 
BEGIN
 
 
	SET @xmlBody  = CAST(@rawXMLConfig AS XML);
 
	INSERT INTO @phoneCommunicationTypeTable
	VALUES('0DA6A26B-D7BC-DF11-B00F-001D60E938C6') ,
		('3DDDB3CC-53EE-49C4-A71F-E9E257F59E49') ,
		('D4A2DC80-30CA-DF11-9B2A-001D60E938C6') ,
		('2B387201-67CC-DF11-9B2A-001D60E938C6') ,
		('6A3FB10C-67CC-DF11-9B2A-001D60E938C6') ,
		('E9D91E45-8D92-4E38-95A0-EF8AA28C9E7A') 
 
 
	INSERT INTO @accountRulesConfig (RuleId, SchemaName, ParentSchemaName, ColumnName, NormalizeFnPattern, CleanDataSchemaName)
	VALUES 	(@webAndAccountNameRule, @accountCommunicationSchemaName, @accountSchemaName, @accountCommunicationColumn,  @webNormalizeFn + '(N##VALUE##)', @accountCommunicationCleanDataSchemaName),
			(@webAndAccountNameRule, @accountSchemaName, NULL, @accountNameColumn,  @baseNormalizeFn + '(N##VALUE##,N''' + @nameNormalizePattern + ''')',  @accountCleanDataSchemaName),
			(@phoneAndAccountNameRule, @accountCommunicationSchemaName, @accountSchemaName, @accountCommunicationPhoneColumn,  @phoneNormalizeFn + '(##VALUE##)', @accountCommunicationCleanDataSchemaName),
			(@phoneAndAccountNameRule, @accountSchemaName, NULL, @accountNameColumn,  @baseNormalizeFn + '(N##VALUE##,N''' + @nameNormalizePattern + ''')', @accountCleanDataSchemaName),
			(@cityAndAccountNameRule, @accountAddressSchemaName, @accountSchemaName, @accountCityColumn, NULL, NULL),
			(@cityAndAccountNameRule, @accountSchemaName, NULL, @accountNameColumn, @baseNormalizeFn + '(N##VALUE##,N''' + @nameNormalizePattern + ''')', @accountCleanDataSchemaName),
			(@countryAndAccountNameRule, @accountAddressSchemaName, @accountSchemaName, @accountCountryColumn, NULL,NULL),
			(@countryAndAccountNameRule, @accountSchemaName, NULL, @accountNameColumn, @baseNormalizeFn + '(N##VALUE##,N''' + @nameNormalizePattern + ''')', @accountCleanDataSchemaName),
			(@AccountInnRule, @accountSchemaName, NULL, @accountInnColumn, @baseNormalizeFn + '(N##VALUE##,N''' + @innNormalizePattern + ''')', NULL),
			(@AccountPhoneRuleUsr, @accountCommunicationSchemaName, @accountSchemaName, @accountCommunicationPhoneColumn,  @phoneNormalizeFn + '(##VALUE##)', NULL),
			(@AccountNameRule, @accountSchemaName, NULL, @accountNameColumn, @baseNormalizeFn + '(N##VALUE##,N''' + @nameNormalizePattern + ''')', @accountCleanDataSchemaName);
 
	INSERT INTO @parsedConfig
	SELECT NULLIF(p.value('(./schemaName)[1]', 'VARCHAR(128)'),'') AS SchemaName,
		NULLIF(p.value('(./parentSchemaName)[1]', 'VARCHAR(128)'),'') AS ParentSchemaName,
		NULLIF(p.value('(./columnName)[1]', 'NVARCHAR(128)'),'') AS ColumnName,
		NULLIF(p.value('(./columnValue)[1]', 'NVARCHAR(4000)'),'') AS ColumnValue,
		NULLIF(p.value('(./typeId)[1]', 'NVARCHAR(128)'),'') AS ColumnValueTypeId
		FROM @xmlBody.nodes('/columns/item') t(p)
 
	UPDATE	@parsedConfig 
	SET ColumnValue = dbo.fn_GetPhoneNumberSearchForm(ColumnValue)
	WHERE ColumnName = @accountCommunicationPhoneColumn
 
	DECLARE activeRuleList CURSOR
	FOR SELECT Id from DuplicatesRule
		WHERE ObjectId = @leadSchemaUId
		AND Id IN (SELECT RuleId FROM @accountRulesConfig)
		AND isActive = 1;
 
	OPEN activeRuleList
	FETCH NEXT
		FROM activeRuleList INTO @ruleId 
 
	WHILE @@FETCH_STATUS = 0
	BEGIN
 
		SET @execStmt = NULL;
		SET @countDetailValues = 0;
		SET @equalQueryConditions = NULL;
		SET @inQueryConditions = NULL;
 
 
		IF EXISTS (SELECT NULL
			FROM @accountRulesConfig config
			LEFT JOIN @parsedConfig parsed
			ON config.ColumnName = parsed.ColumnName
			AND config.SchemaName = parsed.SchemaName
			WHERE parsed.ColumnName IS NULL 
			AND config.RuleId = @ruleId)
		BEGIN 
			FETCH NEXT
			FROM activeRuleList INTO @ruleId
			CONTINUE
		END
		ELSE
		BEGIN	
			IF EXISTS (
				SELECT NULL
					FROM @parsedConfig parsed, @accountRulesConfig config
					WHERE parsed.ColumnName =config.ColumnName
					AND parsed.SchemaName = config.SchemaName
					AND config.ParentSchemaName IS NULL
					AND parsed.ColumnValue IS NULL
					AND config.RuleId = @ruleId)
			BEGIN
				FETCH NEXT
					FROM activeRuleList INTO @ruleId
				CONTINUE
			END
			ELSE
			BEGIN
				DELETE FROM @preStmtValues
				INSERT INTO @preStmtValues (ColumnName, ColumnValue, SchemaName)
				SELECT ISNULL(rulesCfg.CleanDataSchemaName, rulesCfg.SchemaName)+'.'+rulesCfg.ColumnName,
						CASE WHEN NormalizeFnPattern IS NOT NULL THEN 
							REPLACE(NormalizeFnPattern, '##VALUE##', QUOTENAME(parsedCfg.ColumnValue, ''''))
						ELSE QUOTENAME(parsedCfg.ColumnValue, '''') END ColumnValue, 
						ISNULL(rulesCfg.CleanDataSchemaName, rulesCfg.SchemaName)
					FROM @accountRulesConfig rulesCfg, 
						 @parsedConfig parsedCfg
					WHERE rulesCfg.ColumnName = parsedCfg.ColumnName
					AND rulesCfg.SchemaName = parsedCfg.SchemaName
					AND rulesCfg.ParentSchemaName IS NULL
					AND RuleId = @ruleId
 
				SET @queryColumnName = 'Id';
 
				SELECT TOP 1 @schemaName = SchemaName FROM @preStmtValues 
 
				SELECT DISTINCT @inQueryConditions = 
					' AND ' + ColumnName + ' IN (' + STUFF((SELECT ',' + ColumnValue FROM @preStmtValues f 
					WHERE f.ColumnName = t.ColumnName AND f.ColumnName IN (
						SELECT t.ColumnName 
							FROM @preStmtValues t 
						GROUP BY ColumnName HAVING COUNT(*) > 1)
					FOR XML PATH(''), TYPE).value('(./text())[1]','nvarchar(max)'), 1,1, '') +')' FROM @preStmtValues t
 
				SELECT DISTINCT @equalQueryConditions = 
					STUFF((SELECT ' AND ' 
							+ ColumnName + ' LIKE ' 
							+ ColumnValue FROM @preStmtValues f
					WHERE f.ColumnName IN (
						SELECT t.ColumnName 
							FROM @preStmtValues t 
						GROUP BY ColumnName HAVING COUNT(*) = 1) 
					FOR XML PATH(''), TYPE).value('(./text())[1]','nvarchar(max)'), 1,1, '')
 
				SET @execStmt = 
					N'SELECT TOP '+CAST(@offsetLimit as NVARCHAR)+' '+@queryColumnName + CHAR(10) + 
					'FROM '+ CHAR(10) +
					@schemaName + CHAR(10) +
					'WITH (NOLOCK) ' + CHAR(10) +
					'WHERE 1=1'+ CHAR(10);
 
				IF @equalQueryConditions IS NOT NULL
				BEGIN
					SET @execStmt = @execStmt + CHAR(10) + 
					@equalQueryConditions
				END
 
				IF @inQueryConditions IS NOT NULL
				BEGIN
					SET @execStmt = @execStmt + CHAR(10) + 
					@inQueryConditions
				END
 
 
				IF EXISTS (SELECT NULL FROM @accountRulesConfig 
								WHERE RuleId = @ruleId
								AND ParentSchemaName IS NOT NULL)
				BEGIN
					IF EXISTS (
						SELECT NULL
						 FROM @parsedConfig parsed, @accountRulesConfig config
							WHERE parsed.ColumnName =config.ColumnName
								AND parsed.SchemaName = config.SchemaName
								AND parsed.ParentShemaName = config.ParentSchemaName
								AND parsed.ColumnValue IS NOT NULL
								AND config.RuleId = @ruleId)
					BEGIN
 
						DELETE FROM @preStmtValues
						INSERT INTO @preStmtValues (ColumnName, ColumnValue, SchemaName, ColumnValueTypeId)
						SELECT ISNULL(rulesCfg.CleanDataSchemaName, rulesCfg.SchemaName)+'.'+rulesCfg.ColumnName, 
							CASE WHEN NormalizeFnPattern IS NOT NULL THEN 
							REPLACE(NormalizeFnPattern, '##VALUE##', QUOTENAME(parsedCfg.ColumnValue, ''''))
							ELSE QUOTENAME(parsedCfg.ColumnValue, '''') END ColumnValue, 
							ISNULL(rulesCfg.CleanDataSchemaName, rulesCfg.SchemaName),
							ColumnValueTypeId
							FROM @accountRulesConfig rulesCfg, 
								 @parsedConfig parsedCfg
							WHERE rulesCfg.ColumnName = parsedCfg.ColumnName
							AND rulesCfg.ParentSchemaName = parsedCfg.ParentShemaName
							AND rulesCfg.SchemaName = parsedCfg.SchemaName
							AND RuleId = @ruleId
 
 
						SET @queryColumnName = 'AccountId';
 
						IF EXISTS (
							SELECT NULL 
								FROM @phoneCommunicationTypeTable 
								WHERE Id in (SELECT ColumnValueTypeId FROM @preStmtValues f))
						BEGIN 
							INSERT INTO @preStmtValues (ColumnName, ColumnValue, SchemaName)
							SELECT @communicationTypeIdColumn, 
							'''' + CAST(Id AS NVARCHAR(50)) + '''', 
							(SELECT TOP 1 SchemaName FROM @preStmtValues)
							FROM @phoneCommunicationTypeTable
						END
						ELSE 
						BEGIN
							INSERT INTO @preStmtValues (ColumnName, ColumnValue, SchemaName)
							SELECT @communicationTypeIdColumn, 
							'''' + ColumnValueTypeId + '''',
							SchemaName FROM @preStmtValues
							WHERE ColumnValueTypeId IS NOT NULL
						END	
 
						SELECT TOP 1 @schemaName = SchemaName FROM @preStmtValues 
 
						SELECT DISTINCT @inQueryConditions = 
							' AND ' + ColumnName + ' IN (' + STUFF((SELECT ',' + ColumnValue FROM @preStmtValues f 
							WHERE f.ColumnName = t.ColumnName AND f.ColumnName IN (
								SELECT t.ColumnName 
									FROM @preStmtValues t 
								GROUP BY ColumnName HAVING COUNT(*) > 1)
							FOR XML PATH(''), TYPE).value('(./text())[1]','nvarchar(max)'), 1,1, '') +')' FROM @preStmtValues t
 
						SELECT DISTINCT @equalQueryConditions = 
							STUFF((SELECT ' AND ' 
									+ ColumnName + ' LIKE ' 
									+ ColumnValue FROM @preStmtValues f
							WHERE f.ColumnName IN (
								SELECT t.ColumnName 
									FROM @preStmtValues t 
								GROUP BY ColumnName HAVING COUNT(*) = 1) 
							FOR XML PATH(''), TYPE).value('(./text())[1]','nvarchar(max)'), 1,1, '')
 
						IF @execStmt IS NOT NULL
						BEGIN
							SET @execStmt = 
							N'SELECT TOP '+CAST(@offsetLimit as NVARCHAR)+' '+@queryColumnName + CHAR(10) + 
							'FROM ' + CHAR(10) + 
							@schemaName + CHAR(10) +
							'WITH (NOLOCK) ' + CHAR(10) +
							'WHERE '+ @queryColumnName + CHAR(10) + 
							' IN ('	+ @execStmt + ')';
 
							IF @equalQueryConditions IS NOT NULL
							BEGIN
								SET @execStmt = @execStmt + CHAR(10) + 
								@equalQueryConditions;
							END	
 
							IF @inQueryConditions IS NOT NULL
							BEGIN
								SET @execStmt = @execStmt + CHAR(10) + 
								@inQueryConditions;
							END	
 
							INSERT INTO @resultIdsTable
							EXEC sp_executesql @execStmt;
						END
					END
				END
				ELSE
				BEGIN
					INSERT INTO @resultIdsTable
					EXEC sp_executesql @execStmt;
				END
			END
		END
 
	FETCH NEXT
		FROM activeRuleList INTO @ruleId
	END
	CLOSE activeRuleList
	DEALLOCATE activeRuleList
 
	DELETE
		FROM @resultIdsTable
		WHERE Id = @primaryColumnValue
 
	SELECT DISTINCT TOP (@offsetLimit) Id 
		FROM @resultIdsTable
 
END

 

Нравится

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

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

Кастомизация правил поиска похожих лидов осуществляется по инструкции ниже.

1. Необходимо добавить скриптом новое правило в таблицу DuplicatesRule.

Пример скрипта:

insert into DuplicatesRule

(Name, IsActive, ObjectId)

values

('Имя правила', 1, '41AF89E9-750B-4EBB-8CAC-FF39B64841EC')

 

2. Заместить хранимую процедуру tsp_FindAccountSimilarRecordsMSSQL (для примера поиска по контрагентам, по контактам соответственно tsp_FindContactSimilarRecordsMSSQL). Для этого необходимо скопировать весь код из tsp_FindAccountSimilarRecordsMSSQL и дублировать его в новый SQL Script.

3. Объявить своё правилj в блоке с остальными правилами, где указать id добавленного правила с пункта 1 (из таблицы DuplicatesRule) http://prntscr.com/e2m5wz

4. Аналогично существующим правилам, добавить и своё в @accountRulesConfig http://prntscr.com/e2m72y

Например, если правило только для Телефона, копируем выделенную строчку на скриншоте и заменяем название правила на кастомное: http://prntscr.com/i5yogj 

5. Сохранить хранимую процедуру и выполнить установку в БД.

Если привязаться к Вашему коду, то ошибка вероятнее всего в п. 4. , т.к. правило определено неправильно: http://prntscr.com/i5yppg

 

Приятной работы

 

Пробовал и полностью скопировав это правило (если вы про отсутствие @accountCleanDataSchemaName в конце) - не работает.

Что интересно, если я прописываю правило с поиском по ИНН+Телефон, то поиск отрабатывает корректно - проверяет совпадение в обоих полях. Но как только пробую оставить ТОЛЬКО по телефону, то такая дедубликация не работает.

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

Правила поиска дублей для похожих контрагентов/контактов в лиде сделаны таким образом, что нет возможности обращаться отдельно к таблице средств связи, по которой и происходит поиск только по телефону. Логика хранимых процедур была написана с учётом базовых правил, которые предполагают поиск похожих контактов/контрагентов только по правилам, которые включают поиск в таблице Account/Contact плюс таблица средств связи. А обращение только к таблице средств связи в текущей реализации хранимой процедуры не предусмотрено.

Для работы своего правила только по телефону или любого другого средства связи, необходимо внести изменения в хранимую процедуру tsp_FindAccountSimilarRecords, а именно вместо блока "IF @execStmt IS NOT NULL..."  (http://prntscr.com/ibe672) добавить код ниже:



               SET @detailsSelectQuery = N'SELECT TOP '+ CAST(@offsetLimit as NVARCHAR) +

                ' ' + @queryColumnName + CHAR(10) + 

                'FROM ' + CHAR(10) + @schemaName + CHAR(10) +

                'WITH (NOLOCK) ' + CHAR(10) +

                'WHERE 1=1 ';



                IF @execStmt IS NOT NULL

                BEGIN

                    SET @detailsSelectQuery = 

                    @detailsSelectQuery + CHAR(10) + 'AND' + CHAR(10) + @queryColumnName + CHAR(10) + ' IN ('    + @execStmt + ')';

                END



                IF @equalQueryConditions IS NOT NULL

                BEGIN

                    SET @detailsSelectQuery = @detailsSelectQuery + CHAR(10) + 

                    @equalQueryConditions;

                END



                IF @inQueryConditions IS NOT NULL

                BEGIN

                    SET @detailsSelectQuery = @detailsSelectQuery + CHAR(10) + @inQueryConditions;

                END



                IF @detailsSelectQuery IS NOT NULL

                BEGIN

                    INSERT INTO @resultIdsTable

                    EXEC sp_executesql @detailsSelectQuery;

                END

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

При выборе в заказе дополнительную единицу измерения (например, упак = 10 шт, шт - базовая ед.измерения), то цена остается за базовую единицу, а сумма считается с учетом коэффициента. Сумма считается верно, а вот цена остается за базовую единицу. В печатной форме выводятся недостоверные данные. 

Например, 

 Товар1 стоит 5 руб. за шт.

В заказе 1 упак ( упак = 10 шт)

Сумма = 5*1*10 = 50 руб, все верно. В печатной же форме заказе получается так 5*1=50

 

Как быть в такой ситуации? 

Нравится

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

Добрый день, Ильмир!

Печатная форма только отображает значения из тех полей, которые вытянули в нее. На данный момент в базовом функционале системы просто нет возможности выводить агрегированные колонки в редактируемом реестре (к которым и относиться продукт в заказе/счете, график поставок и оплат и т.д.). В данном случае Вы можете реализовать обработчик на поле "Цена", в котором записывать значение = Базовая цена продукта * Количество единиц измерения из детали "Единицы измерения" в продукте. С примерами добавления расчетных полей можно ознакомиться здесь: https://academy.terrasoft.ua/documents/technic-sdk/7-11/dobavlenie-vych…;

 

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

Нужно установить значение списочного поля в зависимости от значения чекбокса.

Новые данные беру из базы.

Вот код метода:

IsKeyContact: function() {
				var isKeyContact = this.get("UsrIsKeyContact");
				var self = this;
				var oldLoyality = self.get("UsrContactLoyality");
 
				var esq = Ext.create("Terrasoft.EntitySchemaQuery", { rootSchemaName: "UsrContactLoyality"});
				esq.addColumn("Name");
				if (isKeyContact)
				{
					esq.filters.add("Name", Terrasoft.createColumnFilterWithParameter(
						Terrasoft.ComparisonType.EQUAL, "Name", "Лояльный"));
					esq.getEntityCollection(function(result) {
						if (result.success) {
							Terrasoft.each(result.collection.getItems(), function(item) {
								self.log(item.values);
								self.set("UsrContactLoyality", item.values);
							});
						}
					});
				}
				else
				{
					esq.filters.add("Name", Terrasoft.createColumnFilterWithParameter(
						Terrasoft.ComparisonType.EQUAL, "Name", "Неопределенна"));
					esq.getEntityCollection(function(result) {
						if (result.success) {
							Terrasoft.each(result.collection.getItems(), function(item) {
								self.log(item.values);
								self.set("UsrContactLoyality", item.values);
							});
						}
					});
				}
			}

 

Нравится

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

Создал замещающий модуль на страницу редактирования контакта, на булевскую колонку.

Подскажите может я не так делаю что.

При изменении значения получаю ошибку в консоли:

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

 

define("ContactPageV2", [], function() {
	return {
		entitySchemaName: "Contact",
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		attributes: {
			"UsrContactLoyality": {
				"dataValueType": Terrasoft.DataValueType.LOOKUP,
				"dependencies": [
					{
						"columns": ["UsrIsKeyContact"],
						"methodName": "IsKeyContact"
					}
				]
			}
		},
		modules: /**SCHEMA_MODULES*/{
			IsKeyContact: function() {
				var isKeyContact = this.get("UsrIsKeyContact");
				this.log(isKeyContact);
			}
 
		}/**SCHEMA_MODULES*/,
		diff: /**SCHEMA_DIFF*/[
			{
				"operation": "merge",
				"name": "PhotoTimeZoneContainer",
				"values": {
					"layout": {
						"colSpan": 24,
						"rowSpan": 1,
						"column": 0,
						"row": 0
					}
				}
			},
			{
				"operation": "merge",
				"name": "AccountName",
				"values": {
					"layout": {
						"colSpan": 24,
						"rowSpan": 1,
						"column": 0,
						"row": 1
					}
				}
			},
			{
				"operation": "merge",
				"name": "JobTitleProfile",
				"values": {
					"layout": {
						"colSpan": 24,
						"rowSpan": 1,
						"column": 0,
						"row": 2
					}
				}
			},
			{
				"operation": "merge",
				"name": "AccountMobilePhone",
				"values": {
					"layout": {
						"colSpan": 24,
						"rowSpan": 1,
						"column": 0,
						"row": 3
					}
				}
			},
			{
				"operation": "merge",
				"name": "AccountPhone",
				"values": {
					"layout": {
						"colSpan": 24,
						"rowSpan": 1,
						"column": 0,
						"row": 4
					}
				}
			},
			{
				"operation": "merge",
				"name": "AccountEmail",
				"values": {
					"layout": {
						"colSpan": 24,
						"rowSpan": 1,
						"column": 0,
						"row": 5
					}
				}
			},
			{
				"operation": "merge",
				"name": "Type",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 0,
						"row": 0
					}
				}
			},
			{
				"operation": "merge",
				"name": "Owner",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 12,
						"row": 0
					}
				}
			},
			{
				"operation": "merge",
				"name": "SalutationType",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 0,
						"row": 1
					}
				}
			},
			{
				"operation": "merge",
				"name": "Gender",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 12,
						"row": 1
					}
				}
			},
			{
				"operation": "merge",
				"name": "Language",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 12,
						"row": 2
					}
				}
			},
			{
				"operation": "insert",
				"name": "GeneralInfoTabGroup226c48fc",
				"values": {
					"caption": {
						"bindTo": "Resources.Strings.GeneralInfoTabGroup226c48fcGroupCaption"
					},
					"itemType": 15,
					"markerValue": "added-group",
					"items": []
				},
				"parentName": "GeneralInfoTab",
				"propertyName": "items",
				"index": 5
			},
			{
				"operation": "insert",
				"name": "GeneralInfoTabGridLayout1e39f378",
				"values": {
					"itemType": 0,
					"items": []
				},
				"parentName": "GeneralInfoTabGroup226c48fc",
				"propertyName": "items",
				"index": 0
			},
			{
				"operation": "insert",
				"name": "UsrIsKeyContactb6f672ab-d08b-41ef-9f88-33af0ac7f901",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 0,
						"row": 0,
						"layoutName": "GeneralInfoTabGridLayout1e39f378"
					},
					"bindTo": "UsrIsKeyContact"
				},
				"parentName": "GeneralInfoTabGridLayout1e39f378",
				"propertyName": "items",
				"index": 0
			},
			{
				"operation": "insert",
				"name": "UsrContactLoyalityd61aa5f3-dda2-413b-8e76-ea6a0cc95c03",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 12,
						"row": 0,
						"layoutName": "GeneralInfoTabGridLayout1e39f378"
					},
					"bindTo": "UsrContactLoyality"
				},
				"parentName": "GeneralInfoTabGridLayout1e39f378",
				"propertyName": "items",
				"index": 1
			},
			{
				"operation": "merge",
				"name": "Job",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 0,
						"row": 0
					}
				}
			},
			{
				"operation": "merge",
				"name": "JobTitle",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 12,
						"row": 0
					}
				}
			},
			{
				"operation": "merge",
				"name": "Department",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 0,
						"row": 1
					}
				}
			},
			{
				"operation": "merge",
				"name": "DecisionRole",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 12,
						"row": 1
					}
				}
			}
		]/**SCHEMA_DIFF*/,
		methods: {},
		rules: {},
		businessRules: /**SCHEMA_BUSINESS_RULES*/{}/**SCHEMA_BUSINESS_RULES*/
	};
});

 

Нравится

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

Добрый день

У вас метод IsKeyContact находится в секции modules, а должен в methods

Артем Гура,

И правда, спасибо большое.

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

Добрый день, ситуация такова: в разделе "лиды" есть 2 страницы для редактирования. На одной из них присутствуют AccountProfile и ContactProfile. Нужно добавить их и на другую страницу, скажите пожалуйста можно ли это сделать и как?

Нравится

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

Добрый день, Вячеслав!

Когда в мастере разделов вы добавили еще одну страницу редактирования, она была сгенерирована и добавленна в конфигурацию.

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

Пример добавления AccountProfile на страницу ContactPageV2.

define("ContactPageV2", ["BaseFiltersGenerateModule", "BusinessRuleModule", "ContactPageV2Resources",           
"ConfigurationConstants", "ContactCareer", "DuplicatesSearchUtilitiesV2"], 
function (BaseFiltersGenerateModule, BusinessRuleModule, resources, ConfigurationConstants, ContactCareer) {    
	return {        
		entitySchemaName: "Contact",        
		// Используемые модули.          
		modules: /**SCHEMA_MODULES*/{            
			// Модуль профиля контрагента.            
			"AccountProfile": {                
				// Конфигурация профиля.                
				"config": {                    
					// Название схемы.                    
					"schemaName": "AccountProfileSchema",                    
					// Признак, сообщающий о том, что конфигурация схемы проинициализирована.                    
					"isSchemaConfigInitialized": true,                   
					// Признак, сообщающий о том, что не используется HistoryState.                    
					"useHistoryState": false,                    
					// Параметры профиля.                    
					"parameters": {                       
						// Конфигурация модели представления.                        
						"viewModelConfig": {                            
							// Название колонки связанной сущности.                            
							masterColumnName: "Account"                        
 
						}                    
 
					}                
 
				}            
 
			}        
 
		}/**SCHEMA_MODULES*/,
		// Массив модификаций.        
		diff: /**SCHEMA_DIFF*/[            
			{                
				"operation": "insert",                
				"parentName": "LeftModulesContainer",                
				"propertyName": "items",               
				// Название профиля.                
				"name": "AccountProfile",                
				// Значения.                
				"values": {                  
					// Тип элемента — модуль.                    
					"itemType": Terrasoft.ViewItemType.MODULE              
					}           
					}    
					]/**SCHEMA_DIFF*/    
 
	}; 
 
});

 

Также Вы можете открыть в конфигурации LeadPageV2 и ознакомиться с реализацией добавления AccountProfile и ContactProfile.

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

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

Код установки значения:

 

 Terrasoft.Core.Configuration.SysSettings.SetDefValue(_userConnection, "CRMTMessagesOffset", _messageOffset);
_userConnection.ResetSettingsCache("CRMTMessagesOffset");

 

Нравится

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

Дмитрий, 

Следующий код работает:

//Установить значение системной настройки
Terrasoft.Core.Configuration.SysSettings.SetValue(UserConnection, "SysSettingsName","SysSettingsValue");
 
//Установить значение системной настройки без учета прав
Terrasoft.Core.Configuration.SysSettings.SetValue(UserConnection, UserConnection.RootAdminUnitGroupId, "SysSettingsName", "SysSettingsValue");



                                        

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

Добрый день.

Посчитали "совмещенный" режим не самым полезным для пользователя. Да и повторять логику отображения и доступности кнопок из Page в Section с помощью месседжей - не самый удобный вариант. В связи с этим решили открывать карточку объекта только в Page режиме, минуя совмещенный с реестром. Т.е. чтобы при нажатии на кнопку открыть в реестре, объект открывался только в режиме редактирования. Каким образом это реализовать? Может кто-то уже сталкивался с подобным кейсом?

Нравится

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

самый простой вариант (как мне кажется) переопределить метод

editRecord: function(primaryColumnValue) {
	var activeRow = this.getActiveRow();
	var typeColumnValue = this.getTypeColumnValue(activeRow);
	var schemaName = this.getEditPageSchemaName(typeColumnValue);
	this.set("ShowCloseButton", true);
	this.openCard(schemaName, ConfigurationEnums.CardStateV2.EDIT, primaryColumnValue);
},

в BaseSectionV2 и открывать карточку через window.open()

А можете привести пример синтаксиса использования windows.open()?

editRecord: function(primaryColumnValue) {
	var activeRow = this.getActiveRow();
	var typeColumnValue = this.getTypeColumnValue(activeRow);
	var schemaName = this.getEditPageSchemaName(typeColumnValue);
	this.set("ShowCloseButton", true);
	window.open(Terrasoft.combinePath(Terrasoft.workspaceBaseUrl,"Nui/ViewModule.aspx#CardModuleV2",schemaName, ConfigurationEnums.CardStateV2.EDIT, primaryColumnValue));
	//this.openCard(schemaName, ConfigurationEnums.CardStateV2.EDIT, primaryColumnValue);
}

 

вот еще пример метода как Из карточки детали выполняется открытие счета сразу на редактирование:

 

openInvoicePage: function(invoiceId) {
   var config = {
         schemaName: "InvoicePageV2",
         operation: enums.CardStateV2.EDIT,
         id: invoiceId,
         moduleId: this.getInviocePageSandboxId()
   };
   this.sandbox.publish("OpenCard", config, [this.sandbox.id]);
},

 

Это же можно повторить и для Схем Реестров, Вызов Метода осуществляете предварительно получив Id сущности, что хотите открыть на редактирование из реестра.

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

Добрый день!

Можно ли сделать автоматические создание скриншота дашборда раздела Итоги в конце рабочего дня?

Нравится

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

Здравствуйте, Александр!

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

Мы передали Вашу идею аналитикам продукта, они рассмотрят возможность реализации данной функциональности в последующих релизах продукта.

Приветствую Александр.

у меня данная задача уже решалась в рамках одного из проектов. Постучитесь ко мне с напоминанием после 01 февраля я с вами поделюсь примером реализации. Только реализовывалось у меня в рамках конфигурации BPMOnline Sales Enterprise. Но поидее функционал Дашбоардов стандартный, должно заработать и на других конфигурациях.

Власов Михаил Викторович, добрый день!

Спасибо за предложение! Обязательно напишем. 

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