Основная структура и пользовательский слой: включение по ID, счетчик и возврат деталей

Учебные задачи

Создаем свою настройку группировок для пользователя, получаем настоящий wrapper компоновщика, выключаем и включаем его единственную группу и проверяем применение к эффективным настройкам и полный вывод товаров.

Где и как запускать

Полный серверный общий модуль УчебныеСтруктурыИРесурсы85; полный отдельный модуль своей управляемой формы ниже.

Подготовка

  1. НОВАЯ пустая файловая база 8.5.1.1343: Имя=УчебныеСтруктурыИРесурсы85, управляемое приложение, совместимость НеИспользовать. Без бизнес-метаданных, расширений и заданий. Не рабочая конфигурация. Здесь не запускалось: runtimeVerifiedScenarios=0.

  2. Общий модуль УчебныеСтруктурыИРесурсы85: Сервер=Да, Клиент=Нет, Вызов сервера=Нет, Глобальный=Нет, Привилегированный=Нет. Вставьте весь код одного урока. ВыполнитьПример — ФУНКЦИЯ, возвращающая текст квитанции; не заменяйте ее процедурой.

  3. Обработка УчебныеСтруктурыИРесурсы85 → управляемая форма Пульт → команда Выполнить с одноименным действием и кнопкой. Полный отдельный модуль формы ниже. F7 и обновление только своего нового стенда перед будущим отдельно разрешенным запуском.

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

  5. Источник и настоящий вывод — разные проверки. Скопировать ожидаемые числа в приемник нельзя: процессор получает настоящий собственный скомпилированный макет, и проверки читают его действительный результат.

  6. Собственный запрос Книга/3/250/750 и Ручка/1/50/50; выбор четырех полей, единственная включенная группа деталей без бизнес-метаданных. Реальный вывод — ТаблицаЗначений с двумя строками, количеством 4 и суммой 800.

  7. Обычная коллекция Настройки.Структура и пользовательский объект СтруктураНастроекКомпоновкиДанных — разные типы. Представление и РежимОтображения исходной коллекции читаются только в основном слое; user-wrapper имеет свои собственные разрешенные свойства.

  8. Имя представления применяется к возвращенной квитанции и показывается через Сообщить в форме. Это не подтверждение оформления штатного редактора пользовательских настроек: его UI здесь не запускался.

Функция ВыполнитьПример() Экспорт
    ПроверитьСвойПустойСтенд();
    Если ПривилегированныйРежим() Тогда
        ВызватьИсключение "Привилегированный режим не нужен";
    КонецЕсли;
    Схема = Новый СхемаКомпоновкиДанных;
    Источник = Схема.ИсточникиДанных.Добавить();
    Источник.Имя = "УчебныйИсточник";
    Источник.ТипИсточникаДанных = "Local";
    Набор = Схема.НаборыДанных.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
    Набор.Имя = "УчебныеТовары";
    Набор.ИсточникДанных = Источник.Имя;
    Набор.АвтоЗаполнениеДоступныхПолей = Истина;
    Набор.Запрос = "ВЫБРАТЬ
    |    ""Книга"" КАК Наименование,
    |    3 КАК Количество,
    |    250 КАК Цена,
    |    750 КАК Сумма
    |ОБЪЕДИНИТЬ ВСЕ
    |ВЫБРАТЬ ""Ручка"", 1, 50, 50";
    Настройки = Схема.НастройкиПоУмолчанию;
    Для Каждого ИмяПоля Из СтрРазделить("Наименование,Количество,Цена,Сумма", ",") Цикл
        Выбранное = Настройки.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
        Выбранное.Поле = Новый ПолеКомпоновкиДанных(ИмяПоля);
        Выбранное.Использование = Истина;
    КонецЦикла;
    Детали = Настройки.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
    Детали.Использование = Истина;
    АвтоВыбор = Детали.Выбор.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных"));
    АвтоВыбор.Использование = Истина;
    ИдентификаторСтруктуры = "СтруктураУчебныхТоваров85";
    Настройки.Структура.ИдентификаторПользовательскойНастройки = "";
    Редактор = Новый КомпоновщикНастроекКомпоновкиДанных;
    Редактор.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(Схема));
    Редактор.ЗагрузитьНастройки(Настройки);
    Если Редактор.ПользовательскиеНастройки.Элементы.Найти(ИдентификаторСтруктуры) <> Неопределено Тогда
        ВызватьИсключение "До назначения своего ID такого элемента в user-слое быть не должно";
    КонецЕсли;
    Настройки.Структура.ИдентификаторПользовательскойНастройки = ИдентификаторСтруктуры;
    Настройки.Структура.ПредставлениеПользовательскойНастройки = "Группировки учебных товаров";
    Настройки.Структура.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Обычный;
    Редактор.ЗагрузитьНастройки(Настройки);
    ПользовательскаяСтруктура = Редактор.ПользовательскиеНастройки.Элементы.Найти(ИдентификаторСтруктуры);
    Если ПользовательскаяСтруктура = Неопределено Тогда
        ВызватьИсключение "Компоновщик не включил свою структуру в пользовательские настройки";
    КонецЕсли;
    Если ТипЗнч(ПользовательскаяСтруктура) <> Тип("СтруктураНастроекКомпоновкиДанных") Тогда
        ВызватьИсключение "В пользовательском слое ожидается настоящий объект настройки структуры";
    КонецЕсли;
    Если ПользовательскаяСтруктура.ИдентификаторПользовательскойНастройки <> ИдентификаторСтруктуры Тогда
        ВызватьИсключение "Найден элемент с другим пользовательским ID";
    КонецЕсли;
    ПользовательскаяСтруктура.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Авто;
    Если ПользовательскаяСтруктура.РежимОтображения <> РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Авто Тогда
        ВызватьИсключение "Не установлен режим своего user-объекта структуры";
    КонецЕсли;
    ПроверитьСвоиТовары(Схема, Редактор.ПолучитьНастройки());
    ТекстСхемы = СвояСхемаВСтроку(Схема);
    Если ПользовательскаяСтруктура.Структура.Количество() <> 1 Тогда
        ВызватьИсключение "В своей простой user-структуре ожидается одна группа деталей";
    КонецЕсли;
    ПользовательскаяГруппа = ПользовательскаяСтруктура.Структура.Получить(0);
    Если ТипЗнч(ПользовательскаяГруппа) <> Тип("ГруппировкаКомпоновкиДанных") Тогда
        ВызватьИсключение "Нужна собственная групповая настройка, не массив или готовая строка результата";
    КонецЕсли;
    Если Не ПользовательскаяГруппа.Использование Или ПользовательскаяСтруктура.ПолучитьКоличествоИспользуемых() <> 1 Тогда
        ВызватьИсключение "Начальная собственная группа деталей должна быть включена";
    КонецЕсли;
    ПользовательскаяГруппа.Использование = Ложь;
    Если ПользовательскаяСтруктура.Структура.Количество() <> 1
        Или ПользовательскаяСтруктура.ПолучитьКоличествоИспользуемых() <> 0 Тогда
        ВызватьИсключение "Выключение настройки не должно удалять ее из каталога";
    КонецЕсли;
    ВыключенныеНастройки = Редактор.ПолучитьНастройки();
    Используемые = 0;
    Для Каждого Группа Из ВыключенныеНастройки.Структура Цикл
        Если ТипЗнч(Группа) <> Тип("ГруппировкаКомпоновкиДанных") Тогда
            ВызватьИсключение "Этот собственный отчет не содержит других видов частей";
        КонецЕсли;
        Если Группа.Использование Тогда
            Используемые = Используемые + 1;
        КонецЕсли;
    КонецЦикла;
    Если Используемые <> 0 Тогда
        ВызватьИсключение "User-выключение не применилось к копии эффективных настроек";
    КонецЕсли;
    ПользовательскаяГруппа.Использование = Истина;
    Если ПользовательскаяСтруктура.ПолучитьКоличествоИспользуемых() <> 1 Тогда
        ВызватьИсключение "Не восстановлено использование собственной user-группы";
    КонецЕсли;
    ПроверитьСвоиТовары(Схема, Редактор.ПолучитьНастройки());
    Если Не Детали.Использование Или Настройки.Структура.Количество() <> 1
        Или Настройки.Структура.ИдентификаторПользовательскойНастройки <> ИдентификаторСтруктуры
        Или Настройки.Структура.ПредставлениеПользовательскойНастройки <> "Группировки учебных товаров"
        Или Настройки.Структура.РежимОтображения <> РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Обычный
        Или СвояСхемаВСтроку(Схема) <> ТекстСхемы Тогда
        ВызватьИсключение "Изменение user-слоя затронуло исходную основную схему/настройки";
    КонецЕсли;
    Подпись = Настройки.Структура.ПредставлениеПользовательскойНастройки;
    Настройки.Структура.ИдентификаторПользовательскойНастройки = "";
    Редактор.ЗагрузитьНастройки(Настройки);
    Если Редактор.ПользовательскиеНастройки.Элементы.Найти(ИдентификаторСтруктуры) <> Неопределено Тогда
        ВызватьИсключение "После снятия ID и перезагрузки старой user-структуры быть не должно";
    КонецЕсли;
    ПроверитьСвоиТовары(Схема, Редактор.ПолучитьНастройки());
    Возврат Подпись + ": user-группа 1 → 0 → 1, каталог всегда 1; результат Книга/Ручка, количество 4, сумма 800.";
КонецФункции

Процедура ПроверитьСвоиТовары(Схема, РабочиеНастройки)
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    Макет = КомпоновщикМакета.Выполнить(Схема, РабочиеНастройки, , , Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
    ПроверитьСвойПолныйВывод(Макет, Неопределено);
КонецПроцедуры

Процедура ПроверитьСвойПолныйВывод(Макет, ВнешниеДанные)
    Процессор = Новый ПроцессорКомпоновкиДанных;
    Процессор.Инициализировать(Макет, ВнешниеДанные);
    Вывод = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
    Приемник = Новый ТаблицаЗначений;
    Вывод.ОтображатьПроцентВывода = Ложь;
    Вывод.УстановитьОбъект(Приемник);
    Результат = Вывод.Вывести(Процессор, Ложь);
    Если ТипЗнч(Результат) <> Тип("ТаблицаЗначений") Или Результат.Количество() <> 2
        Или Результат.Колонки.Количество() <> 4 Тогда
        ВызватьИсключение "Настоящий вывод должен дать две строки и четыре колонки";
    КонецЕсли;
    Для Каждого ИмяПоля Из СтрРазделить("Наименование,Количество,Цена,Сумма", ",") Цикл
        Если Результат.Колонки.Найти(ИмяПоля) = Неопределено Тогда
            ВызватьИсключение "Потеряна ожидаемая колонка реального вывода " + ИмяПоля;
        КонецЕсли;
    КонецЦикла;
    Книга = Результат.Найти("Книга", "Наименование");
    Ручка = Результат.Найти("Ручка", "Наименование");
    Если Книга = Неопределено Или Ручка = Неопределено Тогда
        ВызватьИсключение "Не найдены обе реальные исходные строки результата";
    КонецЕсли;
    Если Книга.Количество <> 3 Или Книга.Цена <> 250 Или Книга.Сумма <> 750
        Или Ручка.Количество <> 1 Или Ручка.Цена <> 50 Или Ручка.Сумма <> 50
        Или Результат.Итог("Количество") <> 4 Или Результат.Итог("Сумма") <> 800 Тогда
        ВызватьИсключение "Потеряны или изменены реальные ячейки собственного полного вывода";
    КонецЕсли;
    Сообщить("Настоящий вывод проверен: Книга 3 × 250 = 750, Ручка 1 × 50 = 50; количество 4, сумма 800.");
КонецПроцедуры

Функция СвояСхемаВСтроку(Схема)
    Запись = Новый ЗаписьXML;
    Запись.УстановитьСтроку();
    СериализаторXDTO.ЗаписатьXML(Запись, Схема);
    Возврат Запись.Закрыть();
КонецФункции

Процедура ПроверитьСвойПустойСтенд()
    Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
        ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
    КонецЕсли;
    Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
        ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
    КонецЕсли;
    Источники = Новый Массив;
    Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
    Для Каждого Источник Из Источники Цикл
        Расширения = РасширенияКонфигурации.Получить(, Источник);
        Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
            ВызватьИсключение "Native список расширений должен иметь тип Массив";
        КонецЕсли;
        Если Расширения.Количество() <> 0 Тогда
            ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
        КонецЕсли;
    КонецЦикла;
    Если ТранзакцияАктивна() Тогда
        ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
    КонецЕсли;
КонецПроцедуры
УчебныеСтруктурыИРесурсы85.Пульт

УчебныеСтруктурыИРесурсы85 → Обработки → УчебныеСтруктурыИРесурсы85 → Формы → Пульт → Модуль

Полный модуль собственной управляемой формы; здесь не выполнялся.

&НаКлиенте
Процедура Выполнить(Команда)
    Сообщить(ВыполнитьНаСервере());
КонецПроцедуры

&НаСервереБезКонтекста
Функция ВыполнитьНаСервере()
    Возврат УчебныеСтруктурыИРесурсы85.ВыполнитьПример();
КонецФункции

Разбор по шагам

  1. Пустой ID не включает заданную структуру в user-слой. Сначала загружаем настройки и проверяем отсутствие собственного ID через nullable Найти.

  2. Назначаем исходной коллекции свой непустой ID, понятную подпись и Обычный; ЗагрузитьНастройки заново заполняет пользовательский слой.

  3. Найти возвращает настоящий СтруктураНастроекКомпоновкиДанных. Проверяем Неопределено, точный тип и ID до доступа к его свойствам; не создаем неизвестный wrapper конструктором.

  4. Режим Авто записывается в разрешенное свойство самого user-wrapper, а не в недоступное свойство его пользовательской коллекции. Это подготовка настройки, не доказательство конкретного UI.

  5. Структура wrapper — readonly-ссылка на коллекцию. В ней одна реальная групповая настройка; ее тип и использование проверяются. ПолучитьКоличествоИспользуемых=1 относится к включенным элементам, не числу строк результата.

  6. Выключаем только user-группу. Количество элементов остается 1, используемых становится 0. ПолучитьНастройки применяет user-слой к копии; подсчитываем активные части этой копии, не обещая физически пустой каталог.

  7. Пустой вывод не запускается. Возвращаем использование user-группы в Истина и проверяем счетчик 1. Реальный процессор должен вернуть обе строки и все четыре правильные колонки.

  8. Исходные Детали остаются включенными; ID/подпись/Обычный и полная сериализация исходной схемы не изменяются от user-опыта.

  9. Намеренно снимаем свой ID в основной коллекции и перезагружаем настройки. Старый wrapper не используется; поиск собственного ID возвращает Неопределено, обычный вывод сохраняет 4/800.

Как проверить результат

  1. По ID: отсутствует → настоящий wrapper → отсутствует после снятия ID и reload.

  2. User-каталог имеет 1 элемент, счетчик используемых 1 → 0 → 1. Основная группа всегда включена, эффективная копия во время выключения имеет 0 активных частей.

  3. Три полноценных вывода сверяют настоящие строки Книга/Ручка, четыре колонки, все ячейки, количество 4 и сумму 800. Форма показывает возвращенную подпись основной настройки.

Ожидаемый результат

Настоящий user-wrapper получен по ID, применение выключения проверено на эффективной копии, счетчик 1→0→1; после возврата проверены все ячейки Книга/Ручка и 4/800. Здесь не запускалось в 1С.

На что обратить внимание

  1. У основной коллекции есть ПредставлениеПользовательскойНастройки; в user-объекте СтруктураНастроекКомпоновкиДанных такого свойства нет. У его Структура нельзя читать/писать недоступные в user-слое свойства представления и режима.

  2. Режим Авто самого wrapper имеет собственный подтвержденный контракт. Он не означает, что текущий UI действительно отрисован как Обычный; здесь это не проверялось.

  3. Перезагрузка заново строит user-слой; прежние ссылки после последнего reload не используются. Не меняйте случайные чужие ID и не ищите свою настройку по произвольному индексу.

  4. ПолучитьКоличествоИспользуемых доступен начиная с 8.5.1, поэтому здесь обязательна точная 8.5.1.1343. Не переносите метод на старую платформу без проверки.

  5. Здесь не было запуска в 1С, работы с хранилищем профилей, записи базы или UI-подтверждения. Эксперимент целиком в собственной памяти нового учебного стенда.

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

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.