Хочется запретить смешивать на одном уровне иерархии справочника наличие одновременно и групп и элементов.
Как бы это сделать красиво/правильно/няшно с минимумом нагрузки на систему...?
Пока ограничится отлупом при интерактивном создании элементов/групп.
Работать и на файловой и на скульной чтобы форматобазонезависимо...
.
Какие могут быть варианты?
Для интерактивного запрета ввода "в диалоге" - универсальный код такой:
Процедура ВводНового()
МетаСпр=Метаданные.Справочник(Вид());
Если МетаСпр.КоличествоУровней>1 Тогда
Спр=СоздатьОбъект("Справочник."+Вид());
Если ПустоеЗначение(МетаСпр.Владелец)=0 Тогда
Спр.ИспользоватьВладельца(Владелец);
КонецЕсли;
Если ПустоеЗначение(Родитель)=0 Тогда
Спр.ИспользоватьРодителя(Родитель);
КонецЕсли;
Если Спр.ВыбратьЭлементы()=1 Тогда
Если Спр.ПолучитьЭлемент(0)=1 Тогда
Если Спр.ЭтоГруппа()<>ЭтоГруппа() Тогда
СтатусВозврата(0);
Возврат;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Нагрузки там особой нет - если Спр.ВыбратьЭлементы() нагружает систему, то универсальные средства и не должны использоваться, тогда надо под конкретную задачу лепить.
Для запрета ввода "в списке" - наверное, нормального решения не существует.
Ввод по строке - я от этого отказался, для "прикладных объектов" - ввод в диалоге.
Ввод по строке оставляю только в простейших классификаторах, где не предполагается никакой логики/ограничений при создании/редактировании групп/элементов.
Цитата: Харлампий Дымба от 21 мая 2025, 22:35Для интерактивного запрета ввода "в диалоге" - универсальный код такой:
Человечище!
Просто круть, я не допер до такого варианта. Правда и не думал сильно, но есть сомнение что до этого додумался бы за разумное время.. или вообще...
Скопипастил в копилку!
Вот вариант с использованием 1с++
ТекстSQLЗапроса = "
|SELECT
| СправочникТовары.ID [Товар $Справочник.Товары]
|FROM
| SC55 СправочникТовары WITH (NOLOCK)
|WHERE
| СправочникТовары.PARENTID = :Родитель
|AND
| СправочникТовары.ISFOLDER = (1 + :Группа)
|";
ODBCRecordSet = СоздатьОбъект("ODBCRecordSet");
ODBCRecordSet.УстановитьТекстовыйПараметр("Родитель", Родитель);
ODBCRecordSet.УстановитьТекстовыйПараметр("Группа", ЭтоГруппа());
ТзОтчета = СоздатьОбъект("ТаблицаЗначений");
ТзОтчета = ODBCRecordSet.ВыполнитьИнструкцию(ТекстSQLЗапроса);
Если ТзОтчета.КоличествоСтрок() > 0 Тогда
сообщить("Элементы и группы не могут создаваться на одном уровне иерархии", "i");
СтатусВозврата(0);
Возврат;
КонецЕсли;
Цитата: vladmenleo от 22 мая 2025, 12:04Вот вариант с использованием 1с++
Да, наверняка гораздо быстрее будет. А ещё наверное, можно
SELECT TOP (1) ?
Ну и для подчиненных справочников допилить
Цитата: Злоп от 22 мая 2025, 03:40Скопипастил в копилку!
Там тогда лучше бы сделать глобальной функцией, типа
глПроверкаСоответствияИерархии(Конт, Родитель)
потому что эту проверку надо будет вызывать как минимум в трех местах:
ВводНового в форме элемента;
ВводНового в форме группы;
ПриПереносеЭлементаВДругуюГруппу(<Элемент>,<Группа>) в формах списка с отображением дерева групп.
Причем в последнем случае, надо будет в качестве Родителя передавать <Группа>. А вот владельца брать не и Группа.Владелец, а из Элемент.Владелец, потому что если переносим в корень (группа пустая), то Группа.Владелец будет пуста, хотя по факту владелец элемента не меняется и равен Элемент.Владелец.
Цитата: Харлампий Дымба от 23 мая 2025, 00:34Там тогда лучше бы сделать глобальной функцией, типа
так примерно и сделал. Про перенос групп помню, но делать пока не стал, сделал по твоей указивке, норм.
Еще скрипт набросал, для разноски элементов в автосоздаваемые группы. Разовая задачка, руками бы задолбались вычищать большой справочник от смеси элементов и групп
В результате примерно вот так
отдельно используется СтатусВозврата(0) и Результат - если придется использовать где-то в коде обработок/отчетов для проверки
//***************************************************************************************************
// при вводе нового элемента и группы:
// Процедура ВводНового()
// Конт = глВзятьКонтекст(Контекст);
// Результат = глЗапретСмешенияГруппЭлементов(Конт,Родитель,0);
// Если СтатусВозврата() = 0 Тогда
// Возврат;
// КонецЕсли;
// КонецПроцедуры // ВводНового()
//
// при переносе в другую группу ПриПереносеЭлементаВДругуюГруппу(<Элемент>,<Группа>)
// в формах списка с отображением дерева групп:
// надо в качестве Родителя передавать <Группа>. А вот владельца брать не из Группа.Владелец,
// а из Элемент.Владелец, потому что если переносим в корень (группа пустая), то Группа.Владелец
// будет пуста, хотя по факту владелец элемента не меняется и равен Элемент.Владелец
// Процедура ПриПереносеЭлементаВДругуюГруппу(Элемент,Группа)
// Результат = глЗапретСмешенияГруппЭлементов(Элемент,Группа,0);
// Если СтатусВозврата() = 0 Тогда
// Возврат;
// КонецЕсли;
// КонецПроцедуры // ПриПереносеЭлементаВДругуюГруппу
//
Функция глЗапретСмешенияГруппЭлементов(Конт,Родитель,Режим=0) Экспорт
Результат = 1;
Если ПустоеЗначение(Режим) = 0
Тогда // режим игнорирования проверки, разрешено смешивание
Возврат Результат;
КонецЕсли;
ВидСправочника = ВРег(Конт.Вид());
поз = Найти(ВРег("%Номенклатура%"),"%"+ВидСправочника+"%"); // упрощенно, перечнь где работает
Если поз = 0
Тогда // разрешено смешивание
Иначе // проверить запрет
МетаСпр = Метаданные.Справочник(ВидСправочника);
Если МетаСпр.КоличествоУровней>1 Тогда
Спр = СоздатьОбъект("Справочник."+ВидСправочника);
Если ПустоеЗначение(МетаСпр.Владелец.Выбран()) = 0 Тогда
Спр.ИспользоватьВладельца(Конт.Владелец);
КонецЕсли;
Спр.ИспользоватьРодителя(Родитель);
Если Спр.ВыбратьЭлементы() = 1 Тогда
Если Спр.ПолучитьЭлемент(0) = 1 Тогда
ЭтоЕстьГруппа = Конт.ЭтоГруппа();
Если Спр.ЭтоГруппа() <> ЭтоЕстьГруппа Тогда
Сообщение1 = "Создание "+?(ЭтоЕстьГруппа=0,"элемента","группы");
Предупреждение(Сообщение1+": ОТКАЗ
|здесь разрешено создавать только "+?(ЭтоЕстьГруппа=0,"группы...","элементы..."),5);
Результат = 0;
СтатусВозврата(0);
Возврат Результат;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
//[*]_progadmin 2025-05-23 00:54 добавлено нетиповое
КонецЕсли;
Возврат Результат;
КонецФункции // глЗапретСмешенияГруппЭлементов()