Принудительное добавление прав для любого ответственного
Иногда сталкиваюсь с ситуацией: нужно, чтобы при изменении ответственного в карточке редактирования ему автоматически выдавались права на эту запись.
Предлагаю такой рецепт: в функции btnOKOnClick проверяем, равен ли ответственный в карточке текущему ответственному и менялся ли ответственный вообще. Затем, если успешно отработала функция scr_BaseDBEdit.btnOKOnClick(Control) (проверяем по состоянию датасета, он в этом случае переходит в dstInactive (см. константы состояний в scr_SysEmums), создаём и выполняем SQL-строку, добавляющую запись прав (возможны два варианта: для представления, если текущий пользователь - не администратор, и для таблицы, если он администратор). И обновляем деталь "Доступ".
Предлагаемый пример годится для раздела "Продукты" (используется таблица прав tbl_OfferingRight). Аналогично можно сделать для любого другого раздела: стоит только поменять имя таблицы. Сделано для MSSQL, легко переделывается и для Oracle.
var Dataset = dlData.Dataset;
var DatasetState = Dataset.State;
var ID = Dataset.Values('ID');
var OwnerID = Dataset.Values('OwnerID');
//Требуется ли раздавать права
var NeedInsertRight = Dataset.Values('OwnerID') != Connector.CurrentUser.ContactID &&
Dataset.Datafields.ItemsByName('OwnerID').ValueIsChanged;
scr_BaseDBEdit.btnOKOnClick(Control); //Базовый ОК
//Создаём доступ для записи, если есть такая необходимость
//И если запись по ОК сохранена
if (NeedInsertRight && Dataset.State == dstInactive){
var Prefix = (Connector.CurrentUser.IsAdmin)?'tbl':'vw';
var SQL = 'declare @OwnerID nvarchar(250) \n\n'+
'set @OwnerID = (select top 1 [ID] from [tbl_AdminUnit] \n'+
'where [UserContactID] = \'' + OwnerID + '\') \n\n' +
'if (@OwnerID Is Not Null)\n Begin \n' +
'insert into [' + Prefix + '_OfferingRight] '+
'([ID], [RecordID], [AdminUnitID], [CanRead], [CanWrite], [CanDelete], [CanChangeAccess])'+
' values '+'(newid(), \'' + ID + '\', @OwnerID,1,1,1,0)\n'+
'END';//Если поставить 1,1,1,1 - будет полный набор прав. Нужно варьировать в зависимости от пожеланий КВ.
//Log.Write(1, SQL);
Connector.DBEngine.ExecuteCustomSQL(SQL, System.EmptyValue);
//Обновляем грид
var RightGridDataset = wnd_OfferingEdit.Attributes('NotifyObject').ParentContainer.ParentWindow.
ComponentsByName('wndAccessDetail').Window.NonVisualComponents.ItemsByName('dlData').Dataset;
if (Assigned(RightGridDataset)){
RightGridDataset.Close();
RightGridDataset.Open();
}
}
}
Анатолий, добрый день.
Есть пару замечаний:
1. Не рекомендую размещать подобную логику в обработчике вообще и в обработчике btnOKOnClick в частности. Логику следует реализовать в отдельном методе, а вызывать этот метод стоит из обработчика событий набора данных - идеально для этого подойдет обработчик "AfterPost".
2. Не совсем ясно, зачем в данном конкретном случае понадобилась работа с ExecuteCustomSQL. Ведь можно было бы обойтись стандартными средствами, создав один единственный сервис вставки, в котором потребовалось бы динамически проставлять только одно свойство - таблицу прав. Примеры работы по такой схеме можно посмотреть в scr_Access.
Добрый день, Виталий!
Спасибо за замечания! Справедливо, такие вещи нужно делать AfterPost. Это позволит, прежде всего, отслеживать изменения ответственных не только из карточки редактирования, но и при любом использовании набора данных. Разве что обновление детали прав будет выглядеть сложнее.
Что касается ExecuteCustomSQL, то использование специально сконструированного сервиса хотя и придаст универсальности предлагаемому решению, но лишит его наглядности. Мне показалось, что ExecuteCustomSQL отработает не хуже сервиса, да и работать будет быстрее.
>> Не совсем ясно, зачем в данном конкретном случае понадобилась работа с ExecuteCustomSQL. Ведь можно было бы обойтись стандартными средствами, создав один единственный сервис вставки, в котором потребовалось бы динамически проставлять только одно свойство - таблицу прав. Примеры работы по такой схеме можно посмотреть в scr_Access.
В ряде случаев использование ExecuteCustomSQL предпочтительнее использования сервисов. В частности, если функционал выполняется очень часто, то, на мой взгляд, лучше использовать ExecuteCustomSQL.
>>В ряде случаев использование ExecuteCustomSQL предпочтительнее использования сервисов. В частности, если функционал выполняется очень часто, то, на мой взгляд, лучше использовать ExecuteCustomSQL.
Согласен, бывают ситуации, когда такой подход может быть оправдан требованиями производительности (если видны конкретные потери производительности из-за многократного получения экземпляра сервиса или сборки запроса и по каким-либо причинам не может быть использовано кеширование). В любом случае, вопрос использования ExecuteCustomSQL требует отдельной проработки в каждом конкретном решении и общие рекомендации здесь давать сложно.
Прекрасно! Видны и плюсы и минусы. Если кому-то потребуется решить такую задачу, можно будет взвесить все "за" и "против" и выбрать самый лучший метод.