Ошибка при открытии карточки задачи

Добрый день.

Я создала новое поле в сервисе sq_Task 'Колонка с типом SQL'. Там написала запрос:

case when isnull((SELECT acc.MyColumn FROM tbl_Account acc
 WHERE tbl_Task.AccountID = acc.ID), '') = '' then ''
else
isnull((SELECT StringValue FROM tbl_SystemSetting WHERE Code = 'MyCode'), '')
 + isnull((SELECT cast(acc.MyColumn AS nvarchar(max)) FROM tbl_Account acc
 WHERE tbl_Task.AccountID = acc.ID ), '')
 end

в датасете добавила поле типа справочник и указала там эту колонку, оставив поле "источник" пустым.
Теперь при открытии карточки задачи пользователем бз админских прав у меня вылетает ошибка
"The Select permission was denied on the object 'tbl_Account', database 'CRM', achema 'dbo'"

Что-то с правами не так?

Нравится

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

Kat, да проблема с правами. Если говорить, не вдаваясь сильно глубоко, то Вы должны заменять названия таблиц tbl_Account, tbl_Task на vw_Account, vw_Task если конфигурация работает под пользователем, а не администратором.

Александр, спасибо!
поменяла в своем запросе tbl_Account на vw_Account

Kat, Вы решили проблему частично :)
Под пользователем с правами администратора могут быть нюансы, поэтому Вам необходимо добавить логику перед открытием DataSet - заменять или нет таблицы на вью в БД.

Все работает и под админом корректно сейчас.
На будущее: нужно прямо текст запроса менять перед открытием? Или есть способы попроще?

"Kat" написал:Все работает и под админом корректно сейчас.

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

"Kat" написал:На будущее: нужно прямо текст запроса менять перед открытием? Или есть способы попроще?

По как что способа проще нет. Да и куда уж проще:)

Есть другая проблема. При открытии карточки (только при создании записи не админом), которая на датасет ссылается, где я запрос написала, вылетает ошибка
"Ошибка выполнения метода 'wnd_MyWindowEditOnPrepare'. OLE error 80020102"
Когда отключаю поле с запросом в сервисе, тогда ошибки нет.

Kat, Вы не проверяли с помощью профайлера, какой запрос посылается на сервер при открытии карточки пользователем? Проверьте, пожалуйста, и попробуйте выполнить этот запрос в SQL Management Studio (или Query Analyzer).

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

Так сообщение возникает при открытии карточки, или при попытке сохранения? Отладчик запускается, или просто возникает окно лога?

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

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

Да.вот:

function ProcessBaseDBEditOnPrepare(Window, BaseDBEdit){
	try {
		var Datalink = Window.ComponentsByName('dlData');
		InitializeDBEdit(Datalink, BaseDBEdit, Window);
		if (BaseDBEdit.RecordID == GUID_NULL) {
		    if (BaseDBEdit.IsCopy){
		        CopyRecord(BaseDBEdit, Window);
			} else {
			    AppendRecord(BaseDBEdit, Window);
			}
		} else {
			if (!EditRecord(BaseDBEdit, Window)) {
				return;
			}
		}
		var btnOK = Window.ComponentsByName('btnOK');
		EnableOKButtonByRights(btnOK, BaseDBEdit);
	} finally {/// дебагер кидает сюда
		Window.Attributes('WindowWasPrepared') = true;
	}
}

Если в отладчике переместиться выше, то можно отследить следующее. Мы попадаем в:

function EditRecord(BaseDBEdit, Window) {
	var Dataset = BaseDBEdit.Dataset;
	OpenDatasetWithRecordID(Dataset, BaseDBEdit.RecordID);
	if (IsDatasetEmpty(Dataset)) {
	    var Message = "Запись удалена";
	    if (!Connector.CurrentUser.IsAdmin) {
	        Message += ' ' + "или" + ' ' +
				"текущий пользователь не имеет достаточно прав для чтения записи";
		}
		ShowWarningDialog(Message);
		var btnOK = Window.ComponentsByName('btnOK');
		EnableControl(btnOK, false);
		return false;//проваливаемся до сюда
	}	
	Dataset.Edit();
	SetEditWindowCaption(BaseDBEdit, Window);
	return true;
}

Попадаем сюда, потому что BaseDBEdit.RecordID не нулевой, хотя задачу только создаем.

Kat, попробуйте добавить строчку debugger; сразу после try {. Потом перезапустите Terrasoft и добавьте новую запись. После того, как отладчик остановится на строке c debugger, пройдитесь дальше в ручном режиме и определите, где на самом деле происходит сбой.

Проваливаюсь в:

function AppendRecord(BaseDBEdit, Window) {
	var Dataset = BaseDBEdit.Dataset;
	var Attributes = Window.Attributes;
	var DoDisableEvents = !Attributes('DoNotDisableEvents');
	BaseDBEdit.RecordID = Connector.GenGUID();
	Dataset.DisableGettingDisplayValues();
	try {
	Dataset.Append();
	if (DoDisableEvents) {
		Dataset.DisableEvents();
	}
	try {
		Dataset.ValAsGUID('ID') = BaseDBEdit.RecordID;
		Window.Attributes('RecordID') = BaseDBEdit.RecordID;
		if ((!IsEmptyValue(BaseDBEdit.ParentItemID)) &&
			(!IsEmptyValue(BaseDBEdit.ParentItemFieldName))) {
			var DataField = Dataset.DataFields(BaseDBEdit.ParentItemFieldName);
			if (Assigned(DataField)) {
				DataField.Value = BaseDBEdit.ParentItemID;
			}
		}
		SetDefaultValues(BaseDBEdit);
	} finally {
		if (DoDisableEvents) {
			Dataset.EnableEvents();
		}
	}
	} finally {
		Dataset.EnableGettingDisplayValues();//падает здесь
	}
	SetEditWindowCaption(BaseDBEdit, Window);
}

Думаю, дело в

"Kat" написал:в датасете добавила поле типа справочник и указала там эту колонку, оставив поле "источник" пустым.

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

Попробуйте удалить из датасета поле типа "Справочник" и добавить обычное текстовое поле.

гениально) спасибо огромное за потраченное время!!!

Добрый день у меня та же ошибка. В SelectQuery есть колонка подзапроса, в которой есть колонка с текстом SQL (если ее отключить все работает). Ошибка вылетает только при открытии существующих записей и только если пользователь не администратор. Принажатии на кнопку "добавить" все работает.Вот скриншот. Как это можно обойти.

Михаил, думаю, Вы можете (поскольку всё-равно используете CustomSQL-колонку) внести все фильтры и используемые таблицы внутрь SQL-текста, не используя подзапрос (то есть, использовать CustomSQL-колонку непосредственно в основном запросе). А дальше - как уже было описано ранее: либо

"Kat" написал:поменяла в своем запросе

все tbl_ на vw_, либо

"Осауленко Александр" написал:Вам необходимо добавить логику перед открытием DataSet - заменять или нет таблицы на вью в БД

Лучше, конечно, второй вариант.

Спасибо за совет. Так и сделаю!

Я сделал, как Вы говорили, но под не-админом все равно эта колонка не работает (та же ошибка). На событии BeforeOpen заменяю значение свойства колонки SQLText из

(SELECT	SUM([Invoice].[Amount]) - SUM([Invoice].[PaymentAmount]) AS [DebtorAmount]
	FROM
		[dbo].[tbl_IssueInApplication] AS [IssueInApplication]
	LEFT OUTER JOIN
		[dbo].[tbl_Issue] AS [Issue] ON [Issue].[ID] = [IssueInApplication].[IssueID]
	LEFT OUTER JOIN
		[dbo].[tbl_OfferingInApplication] AS [OfferingInApplication] ON [OfferingInApplication].[ID] = [IssueInApplication].[OfferingInApplicationID]
	LEFT OUTER JOIN
		[dbo].[tbl_Application] AS [Application] ON [Application].[ID] = [OfferingInApplication].[ApplicationID]
	LEFT OUTER JOIN
		[dbo].[tbl_Invoice] AS [Invoice] ON [Invoice].[ApplicationID] = [Application].[ID]
	WHERE([IssueInApplication].[IsPlaced] = :IsPlaced AND
		[Application].[CustomerID] = [tbl_Account].[ID] AND
		[Issue].[StatusID] = :IssueIsClosed AND
		([Invoice].[BillStatusID] = :InvoiceWaiting OR
		[Invoice].[BillStatusID] = :InvoicePartPayed)))

на

(SELECT	SUM([Invoice].[Amount]) - SUM([Invoice].[PaymentAmount]) AS [DebtorAmount]
	FROM
		[dbo].[tbl_IssueInApplication] AS [IssueInApplication]
	LEFT OUTER JOIN
		[dbo].[vw_Issue] AS [Issue] ON [Issue].[ID] = [IssueInApplication].[IssueID]
	LEFT OUTER JOIN
		[dbo].[tbl_OfferingInApplication] AS [OfferingInApplication] ON [OfferingInApplication].[ID] = [IssueInApplication].[OfferingInApplicationID]
	LEFT OUTER JOIN
		[dbo].[vw_Application] AS [Application] ON [Application].[ID] = [OfferingInApplication].[ApplicationID]
	LEFT OUTER JOIN
		[dbo].[vw_Invoice] AS [Invoice] ON [Invoice].[ApplicationID] = [Application].[ID]
	WHERE([IssueInApplication].[IsPlaced] = :IsPlaced AND
		[Application].[CustomerID] = [tbl_Account].[ID] AND
		[Issue].[StatusID] = :IssueIsClosed AND
		([Invoice].[BillStatusID] = :InvoiceWaiting OR
		[Invoice].[BillStatusID] = :InvoicePartPayed)))

в строке

[Application].[CustomerID] = [tbl_Account].[ID] AND

[tbl_Account].[ID] берется из основного селекта.

Также есть еще одна проблема(номер ошибки тот же): не возможно удалить контрагента, если он указан в каком-то контакте. Воспроизводится даже под админом и даже если я эту колонку удаляю или пишу в ней просто 1

Михаил, у Вас в запросе используются как минимум две таблицы (tbl_IssueInApplication и tbl_OfferingInApplication). Они администрируются по записям? Вы смотрели профайлером, какой запрос посылается на сервер при открытии датасета? Предоставьте, пожалуйста, текст запроса и полный текст сообщения об ошибке.

По первой ошибке (открытие карточки редактирования контрагента не админом):
Текст запроса с профайлера:

exec sp_executesql N'SELECT
	[tbl_Account].[ID] AS [ID],
	[tbl_Account].[Name] AS [Name],
	[tbl_Account].[OfficialAccountName] AS [OfficialAccountName],
	[tbl_Account].[AnnualRevenue] AS [AnnualRevenue],
	[tbl_Account].[EmployeesNumber] AS [EmployeesNumber],
	[tbl_Account].[Address] AS [Address],
	[tbl_Account].[AddressTypeID] AS [AddressTypeID],
	[tbl_Account].[Communication1] AS [Communication1],
	[tbl_Account].[Communication1TypeID] AS [Communication1TypeID],
	[tbl_Account].[Communication2] AS [Communication2],
	[tbl_Account].[Communication2TypeID] AS [Communication2TypeID],
	[tbl_Account].[Communication3] AS [Communication3],
	[tbl_Account].[Communication3TypeID] AS [Communication3TypeID],
	[tbl_Account].[Communication4] AS [Communication4],
	[tbl_Account].[Communication4TypeID] AS [Communication4TypeID],
	[tbl_Account].[Communication5] AS [Communication5],
	[tbl_Account].[Communication5TypeID] AS [Communication5TypeID],
	[tbl_City].[Name] AS [CityName],
	[tbl_Account].[CityID] AS [CityID],
	[tbl_Account].[ZIP] AS [ZIP],
	[tbl_Contact].[Name] AS [PrimaryContactName],
	[tbl_Account].[PrimaryContactID] AS [PrimaryContactID],
	[tbl_Country].[Name] AS [CountryName],
	[tbl_Account].[CountryID] AS [CountryID],
	[tbl_State].[Name] AS [StateName],
	[tbl_Account].[StateID] AS [StateID],
	[tbl_Territory].[Name] AS [TerritoryName],
	[tbl_Account].[TerritoryID] AS [TerritoryID],
	[Owner].[Name] AS [OwnerName],
	[tbl_Account].[OwnerID] AS [OwnerID],
	[tbl_Account].[ActivityID] AS [ActivityID],
	[tbl_Activity].[Name] AS [ActivityName],
	[tbl_Account].[FieldID] AS [FieldID],
	[tbl_Field].[Name] AS [FieldName],
	[tbl_Account].[AccountTypeID] AS [AccountTypeID],
	[tbl_AccountType].[Name] AS [AccountTypeName],
	[tbl_AddressType].[Name] AS [AddressTypeName],
	[CommunicationType1].[Name] AS [Communication1TypeName],
	[CommunicationType2].[Name] AS [Communication2TypeName],
	[CommunicationType3].[Name] AS [Communication3TypeName],
	[CommunicationType4].[Name] AS [Communication4TypeName],
	[CommunicationType5].[Name] AS [Communication5TypeName],
	[tbl_Account].[Code] AS [Code],
	[tbl_Account].[TaxRegistrationCode] AS [TaxRegistrationCode],
	[tbl_Account].[CreatedOn] AS [CreatedOn],
	[tbl_Account].[CreatedByID] AS [CreatedByID],
	[CreatedBy].[Name] AS [CreatedByName],
	[tbl_Account].[ModifiedOn] AS [ModifiedOn],
	[tbl_Account].[ModifiedByID] AS [ModifiedByID],
	[ModifiedBy].[Name] AS [ModifiedByName],
	[tbl_Job].[NameOf] AS [JobNameOf],
	(SELECT SUM([Invoice].[Amount]) - SUM([Invoice].[PaymentAmount]) AS [DebtorAmount]	FROM [dbo].[tbl_IssueInApplication] AS [IssueInApplication]	LEFT OUTER JOIN [dbo].[vw_Issue] AS [Issue] ON [Issue].[ID] = [IssueInApplication].[IssueID] LEFT OUTER JOIN [dbo].[tbl_OfferingInApplication] AS [OfferingInApplication] ON [OfferingInApplication].[ID] = [IssueInApplication].[OfferingInApplicationID] LEFT OUTER JOIN [dbo].[vw_Application] AS [Application] ON [Application].[ID] = [OfferingInApplication].[ApplicationID] LEFT OUTER JOIN [dbo].[vw_Invoice] AS [Invoice] ON [Invoice].[ApplicationID] = [Application].[ID] WHERE([IssueInApplication].[IsPlaced] = @P1 AND [Application].[CustomerID] = [tbl_Account].[ID] AND [Issue].[StatusID] = @P2 AND ([Invoice].[BillStatusID] = @P3 OR [Invoice].[BillStatusID] = @P4))) AS [DebtorAmount]
FROM
	[dbo].[vw_Account] AS [tbl_Account]
LEFT OUTER JOIN
	[dbo].[vw_Contact] AS [tbl_Contact] ON [tbl_Contact].[ID] = [tbl_Account].[PrimaryContactID]
LEFT OUTER JOIN
	[dbo].[tbl_Territory] AS [tbl_Territory] ON [tbl_Territory].[ID] = [tbl_Account].[TerritoryID]
LEFT OUTER JOIN
	[dbo].[vw_Contact] AS [Owner] ON [Owner].[ID] = [tbl_Account].[OwnerID]
LEFT OUTER JOIN
	[dbo].[tbl_City] AS [tbl_City] ON [tbl_City].[ID] = [tbl_Account].[CityID]
LEFT OUTER JOIN
	[dbo].[tbl_State] AS [tbl_State] ON [tbl_State].[ID] = [tbl_Account].[StateID]
LEFT OUTER JOIN
	[dbo].[tbl_Country] AS [tbl_Country] ON [tbl_Country].[ID] = [tbl_Account].[CountryID]
LEFT OUTER JOIN
	[dbo].[tbl_Activity] AS [tbl_Activity] ON [tbl_Activity].[ID] = [tbl_Account].[ActivityID]
LEFT OUTER JOIN
	[dbo].[tbl_Field] AS [tbl_Field] ON [tbl_Field].[ID] = [tbl_Account].[FieldID]
LEFT OUTER JOIN
	[dbo].[tbl_AccountType] AS [tbl_AccountType] ON [tbl_AccountType].[ID] = [tbl_Account].[AccountTypeID]
LEFT OUTER JOIN
	[dbo].[vw_Contact] AS [CreatedBy] ON [CreatedBy].[ID] = [tbl_Account].[CreatedByID]
LEFT OUTER JOIN
	[dbo].[vw_Contact] AS [ModifiedBy] ON [ModifiedBy].[ID] = [tbl_Account].[ModifiedByID]
LEFT OUTER JOIN
	[dbo].[tbl_AddressType] AS [tbl_AddressType] ON [tbl_AddressType].[ID] = [tbl_Account].[AddressTypeID]
LEFT OUTER JOIN
	[dbo].[tbl_CommunicationType] AS [CommunicationType1] ON [CommunicationType1].[ID] = [tbl_Account].[Communication1TypeID]
LEFT OUTER JOIN
	[dbo].[tbl_CommunicationType] AS [CommunicationType2] ON [CommunicationType2].[ID] = [tbl_Account].[Communication2TypeID]
LEFT OUTER JOIN
	[dbo].[tbl_CommunicationType] AS [CommunicationType3] ON [CommunicationType3].[ID] = [tbl_Account].[Communication3TypeID]
LEFT OUTER JOIN
	[dbo].[tbl_CommunicationType] AS [CommunicationType4] ON [CommunicationType4].[ID] = [tbl_Account].[Communication4TypeID]
LEFT OUTER JOIN
	[dbo].[tbl_CommunicationType] AS [CommunicationType5] ON [CommunicationType5].[ID] = [tbl_Account].[Communication5TypeID]
LEFT OUTER JOIN
	[dbo].[tbl_Job] AS [tbl_Job] ON [tbl_Job].[ID] = [tbl_Contact].[JobID]
WHERE([tbl_Account].[ID] = @P5)',N'@P1 int,@P2 varchar(8000),@P3 varchar(8000),@P4 varchar(8000),@P5 varchar(8000)',1,'{E78E618C-956B-4D7E-9F6B-53955E31ADB5}','{89E2E62C-E2B0-47E6-A183-B774ED20CDE8}','{E64C1967-77EE-46DD-97D5-C0101067F6FA}','{A0EAB21C-2BB6-4B50-B4D0-90091A091736}'

Таблицы tbl_IssueInApplication и tbl_OfferingInApplication не администрируются по записям.
Скриншот ошибки в файле "Ошибка 1".

Другая ошибка - при открытии окна отображения связанных записей.Воспроизводится не только в контрагентах, а и в других разделах. Я сначала подумал, что это из за 3 пробелов в названии базы данных, но сделал копию без пробелов и ошибка не пропала(. Скриншот в файле "Ошибка 2".

Михаил, а сам запрос средствами SQL выполняется нормально? Посмотрите, пожалуйста, какое значение содержится в CustomSQL-колонке. Может, не совпадают типы контрола окна и возвращаемого значения?

Уже все нормально :smile:. Клиент просто в правах доступа к полям таблиц поставил уровень "Запрет" на поля, которые вытягивались в CustomSQL. Спасибо за помощь.
А ошибка при удалении связанных записей куда то сама исчезла :smile:

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