Добрый день!

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

 

Спасибо!

Нравится

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

Каскадная связь при настройке детали по полю контрагент должна помочь

Каскадная связь при настройке детали по полю контрагент должна помочь

Алексей Следь, спасибо большое!))) В 7.17 не могу её найти((( 

"Удалять записи" не помогает.

 

 

Екатерина, непонятно, почему у Вас подписи переключателей такие, а не «Блокировать удаление, если есть связанные записи в текущем объекте с этим значением» и «Удалять записи из текущего объекта с этим значением», как написано при открытии в дизайнере стандартной детали, вроде «Контрагент в группе». Там у поля связи с разделом выбрано второе значение.

На всякий случай, старая конфигурация доступна на /0/dev_old и можно включить каскадную связь там.

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

Cпасибо большое! Помогло переключение на старую конфигурацию!)

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

Как убрать действие "Удалить" в детали.

Речь идет о кнопках "Копировать/изменить/удалить" во всплывающем окне детали.



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

Необходимо забрать доступ к действию "удалить" в  конкретной детали

Прикрепленные файлы

Нравится

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

1)

getDeleteRecordMenuItem: Terrasoft.emptyFn //добавлять на схемы деталей (пример OrderProductDetailV2) в блок methods

2) Можно создать кастомную операцию (права доступа на операции) и проверять есть ли у пользователя доступ к этой операции. Пример проверки доступа к операции:

            setUserOperationRightsForCreateChange: function() {
                var operationsToRequest = [];
                debugger;
                operationsToRequest.push("CanCreateChange");
                RightUtilities.checkCanExecuteOperations(operationsToRequest, function(result) {
                    if (result) {
                        this.set("CanCreateChange", result.CanCreateChange);
                    }
                }, this);
            },

А не проще ли права доступа на удаление в конкретном объекте настроить?

1)

getDeleteRecordMenuItem: Terrasoft.emptyFn //добавлять на схемы деталей (пример OrderProductDetailV2) в блок methods

2) Можно создать кастомную операцию (права доступа на операции) и проверять есть ли у пользователя доступ к этой операции. Пример проверки доступа к операции:

            setUserOperationRightsForCreateChange: function() {
                var operationsToRequest = [];
                debugger;
                operationsToRequest.push("CanCreateChange");
                RightUtilities.checkCanExecuteOperations(operationsToRequest, function(result) {
                    if (result) {
                        this.set("CanCreateChange", result.CanCreateChange);
                    }
                }, this);
            },

А не проще ли права доступа на удаление в конкретном объекте настроить?

Дмитрий А., 

Правильно Вас понял, что при добавлении этого (getDeleteRecordMenuItem: Terrasoft.emptyFn ) в блок methods схемы детали, мы уберем у детали действие удалить?!



А когда вызывать этот метод(getDeleteRecordMenuItem), при каких обстоятельствах?! 

Соломонов Алексей Михайлович,

Посмотрите что делает этот метод в коробке. Он как раз отвечает за добавление пункта меню.

Вызывается в addRecordOperationsMenuItems схемы BaseGridDetailV2

Мы же замещаем эту функцию и ничего в ней не делаем. Соответственно пункт меню не добавится.

В вашем случае можно проверить есть ли доступ на операцию. Если есть, то вызываем

 

this.callParent(arguments);

 

Дмитрий А.,

Схема деталей куда добавляем (getDeleteRecordMenuItem: Terrasoft.emptyFn) должна как-то ссылаться на BaseGridDetailV2  ?

 

 

Добавить комментарий

Соломонов Алексей Михайлович,

Обычно все детали и так унаследованы от нее. Что-то дополнительно делать не нужно. Если вы будете выполнять проверку доступа к операции, то в зависимости нужно добавить зависимость от 

RightUtilities

Пример:

define("ContactSectionV2", ["RightUtilities"], function(RightUtilities) {
 
...
 
}

 

Стандартными методами вы можете запретить удаление из объекта детали для определенных ролей.

Пункт Delete у всех останется, но пользователю будет выдавать сообщение, что для удаления не хватает прав.



Хотя, признаю, пользователям было бы удобнее сразу видеть, что они что-то не смогут сделать (добавить, исправить, удалить...)

Дмитрий А.,

 

Дело как раз в том, что эта деталь и наследуется либо от:

 - Редактируемая деталь документа ( MOBaseSchema )

 - DocumentDetailV2 ( MODocument )



И не имеет ни каких ссылок на BaseGridDetailV2



Так же как и родители.

 

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

scr_section_administering_tab_objects_dtl_operations_access.png

Пожелание скрытия в реестре недоступных по правам кнопок недавно как раз завели как идею.

Добавить комментарий

Соломонов Алексей Михайлович пишет:

 - Редактируемая деталь документа ( MOBaseSchema )  - DocumentDetailV2 ( MODocument )

А они от чего наследуются? 

Дмитрий А.,

От MODocument, а тот в свою очередь BaseGridDetailV2. С этим благодаря Вам разобрались.



Вы упомянули про проверку.

1)

if (this.$CanManageCaseDetails === true) {

                        this.callParent(arguments);

                    }



2) В свою очередь

this.$CanManageCaseDetails = result.MOCanManageCasePageDetails;





Вы не могли бы пояснить в каких случаях она (1) срабатывает?

Смотрите выше в коде, где result.MOCanManageCasePageDetails заполняют. Название звучит очень похоже на право на операцию у текущего пользователя.

Соломонов Алексей Михайлович,

без полного кода не совсем понимаю о чем речь. 

предлагаю такой вариант:

define("BCSchema1Detail", ["RightUtilities"], function(RightUtilities) {
	return {
		entitySchemaName: "BCPurchasedServices",
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		attributes: {
            CanCreateChange: {
                dataValueType: this.Terrasoft.DataValueType.BOOLEAN,
                type: this.Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
                value: true
            }
		},
		diff: /**SCHEMA_DIFF*/[]/**SCHEMA_DIFF*/,
		methods: {
            init: function() {
                this.callParent(arguments);
                this.setUserOperationRightsForCreateChange();
            },
			setUserOperationRightsForCreateChange: function() {
                var operationsToRequest = [];
                // debugger;
                operationsToRequest.push("CanCreateChange");
                RightUtilities.checkCanExecuteOperations(operationsToRequest, function(result) {
                    if (result) {
                        this.set("CanCreateChange", result.CanCreateChange);
                        console.log(result.CanCreateChange);
                    }
                }, this);
            },
			addRecordOperationsMenuItems: function(toolsButtonMenu) {
				var isDetailEnabled = this.get("IsEnabled");
				if (isDetailEnabled === false) {
					return;
				}
				var copyRecordMenuItem = this.getCopyRecordMenuItem();
				if (copyRecordMenuItem) {
					toolsButtonMenu.addItem(copyRecordMenuItem);
				}
				var editRecordMenuItem = this.getEditRecordMenuItem();
				if (editRecordMenuItem) {
					toolsButtonMenu.addItem(editRecordMenuItem);
				}
				if (this.get("CanCreateChange")) {
					var deleteRecordMenuItem = this.getDeleteRecordMenuItem();
					if (deleteRecordMenuItem) {
						toolsButtonMenu.addItem(deleteRecordMenuItem);
					}
				}
				var recordRightsSetupMenuItem = this.getRecordRightsSetupMenuItem();
				if (recordRightsSetupMenuItem) {
					toolsButtonMenu.addItem(recordRightsSetupMenuItem);
				}
			}
		}
	};
});

Вам надо добавить в Права доступа на операцию новую операцию с именем CanCreateChange. Доступ к этой операции - добавляете нужные роли. Если пользователь попадает в эту роль - увидит кнопку "удалить". Иначе не увидит. После добавления роли нужно перелогиниться.

Дмитрий Антохин пишет:

getDeleteRecordMenuItem: Terrasoft.emptyFn

Дмитрий Антохин,

Сложность возникает с асинхронщиной.

Права проверяются гораздо дольше чем формируются элементы.

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



 

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

Доброго времени суток!

По логике клиента один из разделов заполняется бизнес-процессом, соответственно кнопку "Добавить" в этом модуле необходимо скрыть. Каким образом это можно реализовать?

Нравится

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

Здравствуйте, Константин!
Можно скрыть кнопку таким образом:

var buttons = Ext.get('button-panel'); //получаем блок с кнопками
var buttonAdd = buttons.dom.children[0]; //получаем кнопку "Добавить"
buttonAdd.remove(); //удаляем кнопку
//или
buttonAdd.style.display = "none"; //скрываем кнопку

Благодарю, но вариант не совсем то, что мне нужно
Элементы из DOM'a, помниться мне, я могу получить только после отрисовки раздела, а удалить кнопку нужно до этого. Да и не совсем понятно куда этот код вставлять?

Константин, в 7.1 есть более корректный метод:

this.modifyUtilsConfig = function(config) {
config.items[0].splice(0,1);
}

А вариант с DOM должен работать на init.

ну если говорить о 7.1, то есть метод

getAddButtonVisbility

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

Совершенно верно

Константин, рад, что у Вас получилось.

QArt,

Попробуйте удалить элемент после того как отработает базовая реализация init (после this.callParent(arguments)). В параметре Ext.get() нужно указывать id DOM элемента.

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

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

var Column = Self.CreateComponent('DataGridColumn', 'colProcessed');
grdData.ActiveView.Add(Column);
grdData.ActiveView.ItemsByName('colProcessed').DataFieldName = 'Processed';

Для того, чтобы динамически удалить колонку в реестре, необходимо выполнить следующее:

var ColumnObject = grdData.ActiveView.ItemsByName('colProcessed');
grdData.ActiveView.RemoveItem(ColumnObject);

Нравится

Поделиться

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

При попытки удалить пользовательские отчеты Word выдает ошибку:
"Не удалено 1 из 1 записей
Нет возможности:1
Связанные записи могут существовать в следующих таблицах:
Отчет в группе (tbl_ReportInGroup)
Права доступа к отчетам (tbl_ReportRight)"

Нравится

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

Проверьте в Terrasoft Administrator, установлены ли для связей FReportRightRecordID таблицы tbl_ReportRight и FReportInGroupReportID таблицы tbl_ReportInGroup признаки "Каскадная связь". Попробуйте снять эти галочки, установить заново и пересохранить таблицы. После этого перезапустите программу Terrasoft и попытайтесь удалить отчёт.

Если это не решит проблему, перед удалением отчёта запустите профайлер, попробуйте удалить отчёт, скопируйте из профайлера запрос на удаление, который при этом отправляется на сервер, и попробуйте выполнить его средствами СУБД. Если отчёт не удаляется из-за связанных записей, возникнет сообщение о том, в какой таблице находится запись, связанная с отчётом. В зависимости от таблицы нужно будет либо удалить из неё все записи, связанные с отчетом, либо обнулить значения в поле связи.

Спасибо. помогло №1)

Насколько я помню такие ошибки (удаления) пишутся в лог. Достаточно туда посмотреть, чтобы понять какие таблицы содержат ссылки.

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

Появился вопрос:
Когда я удаляю созданный документ в разделе Документы, то файлы прикрепленные к нему на детали Файлы (файлы сохранены в базу данных) остаются в базе данных. Т.е. чтобы не оставлять этот мусор в базе мне приходиться перед удалением документа вручную удалить прикрепленные файлы.
Как сделать чтобы при удалении документа связанные с ним файлы (сохраненные в базу данных) удалялись автоматически ?
---------------
TS CRM 3.3.1.72
MSSQL 2005

Нравится

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

Наверное придется в обработчик клика кнопки "удалить" писать код для удаления файлов.
Или на вкладке деталей сначала поудалять файлы а потом удалить документ.
Можно еще каскадное удаление сделать для таблицы документ

Только что проверил на 3.3.1 SoftKey - действительно, есть такая проблема. Если удалить "Документ", то триггер (для каскадного удаления) удаляет только линк из таблицы tbl_FileInDocument, а вот сам файл остается в таблице tbl_Files (мусор). Но, если удалить файл из детали "Файлы", тогда он удаляет за собой (опять триггер) из tbl_Files.
Вот здесь бы и пригодилась идея Алексея: http://community.terrasoft.ua/ideas/2789 очень жаль, что отложили :cry:

--
www.it-sfera.com.ua

И все же вернемся к вопросу: каков на данный момент наиболее быстрый и простой способ решения данной ситуации ?

К датасету ds_Document надо добавить обработчик события OnAfterDelete, в котором удалять те файлы из tbl_Files, на которые есть ссылки в tbl_FileInDocument, то есть:
- tbl_FileInDocument.DocumentID = ID удаленного документа
- tbl_FileInDocument.FileID = ссылки на tbl_Files

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

--------------------------------------------
Лабитек
Центр разработки приложений

Спасибо будем посмотреть.

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

Как известно, для удаления записей из таблицы, правильней всего создавать
специальный DeleteQuery, но как показала практика - делать это всем лень :)
для таких случаев была написана следующая функция.

function DeleteRecords(Dataset, Dictionary) {
   if (!Assigned(Dataset)) {
      if (!IsEmptyValue(Dataset) &&
         Assigned(Services.InformationsByUSI(Dataset))) {
         Dataset = GetSingleItemByCode(Dataset, 'DeleteRecords');
      } else {
         return;
      }
   }
   if ('DBDataset' == Dataset.ServiceTypeCode) {
      var Table = Dataset.SelectQuery.Items(0).FromTable;
   } else
   if ('Table' == Dataset.ServiceTypeCode) {
      var Table = Dataset;
   } else {
      return;
   }
   var dq = Services.CreateItem('DeleteQuery');
   dq.Table = Table;
   var TableFields = Table.Fields;
   var Filters = dq.Filters;
   var Parameters = dq.Parameters;

   var TableField;
   var FilterFieldType;
   var CompareOperatorType = cotEqual;
   var Parameter;
       
   var Keys = new VBArray(Dictionary.Keys()).toArray();
   var KeysLength = Keys.length;
   for (var i = 0; i KeysLength; i++) {
      TableField = TableFields.ItemsByName(Keys[i]);
      FilterFieldType =
         GetParameterTypeBySQLDataType(TableField.SQLDataType);
      Parameter = AddQueryParameter(Parameters, Keys[i],
         FilterFieldType, Dictionary(Keys[i]));
      AddQueryCompareFilter(Filters, Keys[i], TableField,
         Parameter, CompareOperatorType);
   }
   return dq.Execute();
}

первый параметр - может быть как именем сервиса так и самим объектом Таблица или Датасет;
второй параметр - это набор полей и их значений в виде Словаря.

Функция апдейта:

function UpdateRecord(Dataset, RecordID, Dictionary) {
   if (!Assigned(Dataset)) {
      if (!IsEmptyValue(Dataset) &&
         Assigned(Services.InformationsByUSI(Dataset))) {
         Dataset = GetSingleItemByCode(Dataset, 'UpdateRecord');
      } else {
         return;
      }
   }
   if ('DBDataset' == Dataset.ServiceTypeCode) {
      var Table = Dataset.SelectQuery.Items(0).FromTable;
   } else
   if ('Table' == Dataset.ServiceTypeCode) {
      var Table = Dataset;
   } else {
      return;
   }
   var uq = Services.CreateItem('UpdateQuery');
   uq.Table = Table;
   var TableFields = Table.Fields;
   var Filters = uq.Filters;
   var Parameters = uq.Parameters;
   var Columns = uq.ColumnsValues;

   var TableField;
   var FieldType;
   var CompareOperatorType = cotEqual;
   var Parameter;
   var Column;
       
   TableField = TableFields.ItemsByName('ID');
   Parameter = AddQueryParameter(Parameters, 'ID', sdtGUID, RecordID);
   AddQueryCompareFilter(Filters, 'ID', TableField,
      Parameter, CompareOperatorType);
       
   var Keys = new VBArray(Dictionary.Keys()).toArray();
   var KeysLength = Keys.length;
   for (var i = 0; i KeysLength; i++) {
      TableField = TableFields.ItemsByName(Keys[i]);   
      if (!Assigned(TableField)) {
         continue;
      }
      FieldType = GetParameterTypeBySQLDataType(TableField.SQLDataType);
      AddQueryParameter(Parameters, Keys[i], FieldType,
         Dictionary(Keys[i]));
      Column = Columns.CreateItem();
      Column.ParameterName = Column.KeyValue = Column.Name = Keys[i];
      Column.DataType = FieldType;
      Columns.Add(Column);
   }
   var Result = uq.Execute();
   return Result;
}

первый параметр - может быть как именем сервиса так и самим объектом Таблица или Датасет;
второй параметр - это ID записи в таблице, которую нужно обновить;
третий параметр - это набор полей и их значений в виде Словаря.

Также нужно подключить scr_DB

Пример использования:

var Dictionary = GetNewDictionary();
Dictionary('AccountID') = RecordID;
Dictionary('TypeID') = tOne;
DeleteRecords('tbl_AccountAddress', Dictionary);

var Dictionary = GetNewDictionary();
Dictionary('Name') = 'NewValue';
Dictionary('Name2') = 'NewValue2';
Dictionary('Name3') = 'NewValue3';
UpdateRecord('tbl_Account', RecordID, Dictionary);

Нравится

Поделиться

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

С некоторых пор функция UpdateRecord уже есть "в коробке", в скрипте scr_JobManagerUtils, но с небольшой доработкой, чтобы не пытались обновить значение ID.
После

      TableField = TableFields.ItemsByName(Keys[i]); 

добавлено:

      if (TableField.SQLName == 'ID') {
          continue;		
	  }
Показать все комментарии