ОписаниеНастроек.По умолчанию

Конструкторы

Также может быть создан с использованием функциональной формы оператора Новый.

Синтаксис

Новый ОписаниеНастроек()
Полное описание, параметры и ограничения

ОписаниеНастроек.По умолчанию

ОписаниеНастроек (SettingsDescription)

По умолчанию

Доступен, начиная с версии 8.2.

Синтаксис:
Новый ОписаниеНастроек()
Описание:

Также может быть создан с использованием функциональной формы оператора Новый.

Использование в версии:

Доступен, начиная с версии 8.2.

Методическая информация

Практические примеры

Создать два настоящих своих варианта, переключить А→Б→А и удалить только их

Будущий BSL только новой базы и нового пользователя создаёт две реальные записи стандартного внутреннего хранилища. Ключ допускается к УстановитьТекущийВариант только после Save, Load, полного typed XML-сравнения НастройкиКомпоновкиДанных и сохранённого описания. Actual ключ/представление формы и полный effective выбор проверяются отдельно. Числа и визуальный результат сверяются вручную, не выводятся из флагов; полный собственный пульт закрывает отчёт до точечного удаления. Здесь записей и runtime0.

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

Смешанный управляемый: толстый клиент 8.5.1.1343 Такси и сервер

Подготовка

  1. Только будущий ручной опыт: создайте совершенно новую пустую учебную информационную базу. Здесь 1С и BSL не запускались; runtime-проверок 0. Не переносите урок в рабочую конфигурацию.

  2. В конфигураторе имя собственной конфигурации задайте УчебныеВариантыПакетов85; основное приложение — управляемое, Режим совместимости — Не использовать. Запуск: толстый клиент в режиме управляемого приложения, установленная платформа ровно 8.5.1.1343, интерфейс Такси, обычный режим основного окна. Обычный режим основного окна не означает обычное приложение: приложение остаётся управляемым. Проверки версии/имени/интерфейса не доказывают, каким исполняемым клиентом был запущен сеанс: проверьте способ запуска вручную.

  3. Создайте нового отдельного пользователя АвторВариантов85 только в этой новой базе. Не переименовывайте и не используйте рабочего пользователя. Сеанс всегда запускайте им: guard проверяет точное ИмяПользователя().

  4. Создайте собственную роль ПакетыУчебные85: доступ только к своему отчёту УчебныеСохраненныеВарианты85, его собственной форме и своему общему пульту, просмотр/использование форм. В правах корня конфигурации включите ТолстыйКлиент (ThickClient), РежимОсновногоОкнаОбычный (MainWindowModeNormal) и СохранениеДанныхПользователя (SaveUserData). После обновления конфигурации базы данных назначьте эту роль новому пользователю АвторВариантов85. Не выдавайте учебному пользователю Администрирование, АдминистрированиеДанных или ОбновлениеКонфигурацииБазыДанных. Отчёт не требует чтения или записи предметных объектов; локальный запрос состоит только из трёх константных строк.

  5. У конфигурации свойства ХранилищеВариантовОтчетов и ХранилищеПользовательскихНастроекОтчетов оставьте незаданными. Это необходимое соответствие стандартному внутреннему хранилищу, которое получает авторский код; при собственном прикладном хранилище отчётный setter мог бы читать другое место.

  6. Метаданные → Отчёты: создайте собственный УчебныеСохраненныеВарианты85. ОсновнаяСхемаКомпоновкиДанных в метаданных не нужна: полный модуль строит собственную схему в памяти и присваивает реальному ОтчетОбъект.СхемаКомпоновкиДанных. Никаких таблиц базы и внешних наборов нет.

  7. В УчебныеСохраненныеВарианты85 → Формы создайте управляемую форму отчёта СохраненныеВарианты85 типа Основная. Не обычную форму. Укажите её основной формой отчёта.

  8. Основной реквизит формы Отчет — ОтчетОбъект.УчебныеСохраненныеВарианты85, флаг Основной. Реквизит Результат — ТабличныйДокумент. Элемент ПолеРезультата — поле табличного документа, ПутьКДанным = Результат. Имена собственные, не предполагаются имена автоматически созданных элементов.

  9. Добавьте реквизиты формы СостояниеУрока (Строка неограниченная), МаршрутКомпоновки (Булево), СобытийДо и СобытийПосле (Число 9,0 неотрицательное). Счётчики относятся только к маршруту событий, не к строкам или числам отчёта. Добавьте поле состояния с ПутьКДанным = СостояниеУрока.

  10. В событиях именно формы назначьте ПриСозданииНаСервере → ПриСозданииНаСервере, ПриКомпоновкеРезультата → ПриКомпоновкеРезультата, ПослеКомпоновкиРезультата → ПослеКомпоновкиРезультата. Не создавайте эти обработчики в модуле объекта отчёта; его одноимённые события имеют другой контракт.

  11. Создайте собственные команды формы и кнопки с действиями: СоздатьСвоиВарианты → СоздатьСвоиВарианты; ВыбратьКраткий → ВыбратьКраткий; ВернутьПодробный → ВернутьПодробный. Все имена обработчиков приведены в основном полном модуле. Штатные произвольные кнопки сохранения/загрузки не используйте в этом опыте.

  12. Точное место основного блока: модуль управляемой формы Отчет.УчебныеСохраненныеВарианты85.Форма.СохраненныеВарианты85. Замените только модуль своей новой формы целиком, не добавляйте неизвестные общие модули и helpers.

  13. Вся схема задаётся основным блоком: источник ИсточникПакетов85 типа Local, набор запроса Пакеты85 с АвтоЗаполнениеДоступныхПолей = Истина; Пакет (Строка), Количество (Число) и Сумма (Число) образуются константным запросом ПакетА/3/60, ПакетБ/1/20, ПакетВ/6/120. Детальные записи без промежуточных или общего итога. Поля выбора Подробно85: Пакет,Количество,Сумма; Кратко85: Пакет,Сумма.

  14. Не привязывайте пригодность схемы или числовую правильность результата к служебному флагу. ПослеКомпоновкиРезультата проверяет только actual тип параметра ТабличныйДокумент и маршрут штатной компоновки. Координаты вывода не предполагаются: полный состав реальных строк и значения читатель проверит в ПолеРезультата вручную.

  15. В report-форме дополнительно реквизиты XMLА и XMLБ — Строка неограниченная. Это полные строковые снимки сериализованного состояния собственных actual настроек, а не адреса файлов.

  16. Метаданные → Общие формы: создайте управляемую ПультСохраненныхВариантов85 без основного реквизита и предметных данных. Команды/кнопки ОткрытьСвойОтчет → ОткрытьСвойОтчет и ЗакрытьИУдалитьСозданное → ЗакрытьИУдалитьСозданное. Событие ПриСозданииНаСервере назначьте одноимённому обработчику. Точное место supporting-блока: модуль общей управляемой формы ПультСохраненныхВариантов85; вставьте полный блок именно туда целиком.

  17. Пульт держит только свой реальный экземпляр РабочаяФорма, полученный с новым УникальныйИдентификатор в четвёртом аргументе ПолучитьФорму. Не открывайте второй отчёт с теми же ключами, не перезапускайте пульт до cleanup и не изменяйте профили через другие формы.

  18. Полный supporting-блок запуска вставьте в модуль управляемого приложения этой новой пустой конфигурации; ПриНачалеРаботыСистемы вызывает только ОбщаяФорма.ПультСохраненныхВариантов85. Для разных уроков запускайте соответствующий полный блок, не три обработчика одинакового имени сразу.

  19. В форме добавьте реквизиты Строка неограниченная: ПользовательОпытов, ОбластьКлючей, ПрефиксКлючей, КлючА, КлючБ, КлючБазы; Булево: СозданА, СозданБ, СозданБаза, ОчиститьА, ОчиститьБ, ОчиститьБазу, ХранилищеПодтверждено. Сгенерированный UUID становится частью строкового namespace только для нового опыта; до фактических Save, Load и полного сравнения это не существующий вариант или профиль.

  20. Сохраняющий код выполняет внутренние записи настроек только при вашем будущем запуске в этой новой базе. Пять аргументов Save: объект, ключ, actual настройки, ОписаниеНастроек с представлением, captured current пользователь; четыре аргумента Load: объект, ключ, output описание, тот же пользователь. Неопределено после Load — отсутствие записи и отказ, не объект настроек.

  21. После precheck отсутствия собственного ключа, до вызова Save фиксируется Очистить* — ownership точного pending ключа; исключение Save не доказывает отсутствие возможной частичной записи. После нормально завершённого Save отдельно фиксируется Создан*. Только после всех typed readback разрешается ХранилищеПодтверждено. Ошибки Save/readback перехватываются внутри серверной процедуры с исходной диагностикой и нормальным возвратом формы; client False не продолжает setter. Квитанция сохраняет все точные pending ключи для узкой cleanup даже при сбое.

  22. Не закрывайте отчёт вручную. Полный supporting-блок пульта получает actual квитанцию у собственного экземпляра, закрывает его и требует Открыта() = Ложь до серверной очистки. Не изменяйте квитанцию и не передавайте в cleanup произвольную структуру; это узкий стенд одного собственного пользователя, не сервис удаления пользовательских ключей.

  23. Очистка удаляет только свои отмеченные pending ключи, отсутствовавшие перед собственным Save, включая возможную частичную запись при его исключении. Ровно три непустые строки: свой объект, свой ключ, свой current пользователь. Namespace и принадлежность квитанции проверяются до Delete; readback должен стать Неопределено. При сбое выводятся точные свои ключи/отметки, квитанция остаётся и очистка не объявляется завершённой. Системное хранилище, текущие ключи формы, историю и все настройки пользователя код не очищает.

  24. После всех подготовок метаданных, реквизитов, событий, команд, полных модулей формы/пульта/управляемого приложения и прав роли автор стенда в конфигураторе сохраняет конфигурацию и выполняет Конфигурация → Обновить конфигурацию базы данных (F7). Подтвердите обновление именно новой учебной базы. Это действие автора стенда, а не требование административных прав у учебного пользователя. После F7 проверьте назначение роли ПакетыУчебные85 пользователю АвторВариантов85 и только затем запускайте собственный управляемый сеанс этим пользователем.

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Попытка
    ПроверитьУчебнуюСреду();
    Если ЭтаФорма.ТипФормыОтчета <> ТипФормыОтчета.Основная Тогда
        ВызватьИсключение "Нужна собственная управляемая форма отчёта Основная";
    КонецЕсли;
    ЭтаФорма.РежимБлокировкиПриОткрытииОкна = РежимБлокировкиПриОткрытииОкнаФормы.НеБлокировать;
    ОбъектОтчета = ЭтаФорма.РеквизитФормыВЗначение("Отчет");
    ОбъектОтчета.СхемаКомпоновкиДанных = СоздатьСобственнуюСхему();
    ОбъектОтчета.КомпоновщикНастроек.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(ОбъектОтчета.СхемаКомпоновкиДанных));
    ОбъектОтчета.КомпоновщикНастроек.ЗагрузитьНастройки(ОбъектОтчета.СхемаКомпоновкиДанных.НастройкиПоУмолчанию);
    ЭтаФорма.ЗначениеВРеквизитФормы(ОбъектОтчета, "Отчет");
    ЭтаФорма.СобытийДо = 0;
    ЭтаФорма.СобытийПосле = 0;
    ЭтаФорма.МаршрутКомпоновки = Ложь;
    ЭтаФорма.СостояниеУрока = "Собственная схема готова; числа и внешний вид не проверены";
    ЭтаФорма.ПользовательОпытов = ИмяПользователя();
    ЭтаФорма.ОбластьКлючей = Строка(Новый УникальныйИдентификатор);
    ЭтаФорма.ПрефиксКлючей = "УчебныеПакеты85_" + ЭтаФорма.ОбластьКлючей + "_";
    ЭтаФорма.КлючА = ЭтаФорма.ПрефиксКлючей + "А";
    ЭтаФорма.КлючБ = ЭтаФорма.ПрефиксКлючей + "Б";
    ЭтаФорма.КлючБазы = "";
    ЭтаФорма.СозданА = Ложь;
    ЭтаФорма.СозданБ = Ложь;
    ЭтаФорма.СозданБаза = Ложь;
    ЭтаФорма.ОчиститьА = Ложь;
    ЭтаФорма.ОчиститьБ = Ложь;
    ЭтаФорма.ОчиститьБазу = Ложь;
    ЭтаФорма.ХранилищеПодтверждено = Ложь;
Исключение
    Отказ = Истина;
    ВызватьИсключение "Подготовка остановлена: " + ОписаниеОшибки();
КонецПопытки;
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ПроверитьУчебнуюСреду()
Если ИмяПользователя() <> "АвторВариантов85" Тогда
    ВызватьИсключение "Нужен отдельный новый именованный пользователь АвторВариантов85";
КонецЕсли;
Если КлиентскоеПриложение.ТекущийВариантИнтерфейса() <> ВариантИнтерфейсаКлиентскогоПриложения.Такси Тогда
    ВызватьИсключение "Нужен собственный толстый управляемый сеанс Такси";
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция СоздатьСобственнуюСхему()
Схема = Новый СхемаКомпоновкиДанных;
Источник = Схема.ИсточникиДанных.Добавить();
Источник.Имя = "ИсточникПакетов85";
Источник.ТипИсточникаДанных = "Local";
Набор = Схема.НаборыДанных.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
Набор.Имя = "Пакеты85";
Набор.ИсточникДанных = Источник.Имя;
Набор.АвтоЗаполнениеДоступныхПолей = Истина;
Набор.Запрос = "ВЫБРАТЬ ""ПакетА"" КАК Пакет, 3 КАК Количество, 60 КАК Сумма
|ОБЪЕДИНИТЬ ВСЕ
|ВЫБРАТЬ ""ПакетБ"", 1, 20
|ОБЪЕДИНИТЬ ВСЕ
|ВЫБРАТЬ ""ПакетВ"", 6, 120";
Схема.ВариантыНастроек.Очистить();
Подробный = Схема.ВариантыНастроек.Добавить();
Подробный.Имя = "Подробно85";
Подробный.Представление = "Все три поля пакетов";
ЗаполнитьНастройки(Подробный.Настройки, "Пакет,Количество,Сумма");
Краткий = Схема.ВариантыНастроек.Добавить();
Краткий.Имя = "Кратко85";
Краткий.Представление = "Пакет и сумма";
ЗаполнитьНастройки(Краткий.Настройки, "Пакет,Сумма");
Возврат Схема;
КонецФункции

&НаСервереБезКонтекста
Процедура ЗаполнитьНастройки(Настройки, ИменаПолей)
Для Каждого ИмяПоля Из СтрРазделить(ИменаПолей, ",") Цикл
    Выбранное = Настройки.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
    Выбранное.Поле = Новый ПолеКомпоновкиДанных(ИмяПоля);
    Выбранное.Использование = Истина;
КонецЦикла;
Детали = Настройки.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
Детали.Использование = Истина;
АвтоВыбор = Детали.Выбор.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных"));
АвтоВыбор.Использование = Истина;
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ПроверитьПолныйВыбор(Настройки, ИменаПолей)
Если ТипЗнч(Настройки) <> Тип("НастройкиКомпоновкиДанных") Тогда
    ВызватьИсключение "Нет типизированных настроек выбора";
КонецЕсли;
Ожидаемые = СтрРазделить(ИменаПолей, ",");
Если Настройки.Выбор.Элементы.Количество() <> Ожидаемые.Количество() Тогда
    ВызватьИсключение "Изменился полный состав выбранных полей";
КонецЕсли;
Для Индекс = 0 По Ожидаемые.Количество() - 1 Цикл
    ПолеВыбора = Настройки.Выбор.Элементы.Получить(Индекс);
    Если ТипЗнч(ПолеВыбора) <> Тип("ВыбранноеПолеКомпоновкиДанных") Тогда
        ВызватьИсключение "В выборе появился неподдерживаемый элемент";
    КонецЕсли;
    Если ПолеВыбора.Поле <> Новый ПолеКомпоновкиДанных(Ожидаемые[Индекс]) Или ТипЗнч(ПолеВыбора.Использование) <> Тип("Булево") Или Не ПолеВыбора.Использование Тогда
        ВызватьИсключение "Не совпало поле или его использование";
    КонецЕсли;
КонецЦикла;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолныйТипизированныйXML(Настройки)
Если ТипЗнч(Настройки) <> Тип("НастройкиКомпоновкиДанных") Тогда
    ВызватьИсключение "Ожидался полный тип НастройкиКомпоновкиДанных";
КонецЕсли;
Писатель = Новый ЗаписьXML;
Писатель.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(Писатель, Настройки, НазначениеТипаXML.Явное);
Текст = Писатель.Закрыть();
Если ТипЗнч(Текст) <> Тип("Строка") Или Текст = "" Тогда
    ВызватьИсключение "Сериализация полного объекта не дала XML";
КонецЕсли;
Читатель = Новый ЧтениеXML;
Читатель.УстановитьСтроку(Текст);
Копия = СериализаторXDTO.ПрочитатьXML(Читатель, Тип("НастройкиКомпоновкиДанных"));
Читатель.Закрыть();
Если ТипЗнч(Копия) <> Тип("НастройкиКомпоновкиДанных") Тогда
    ВызватьИсключение "Полный XML не восстановил тип настроек";
КонецЕсли;
Писатель = Новый ЗаписьXML;
Писатель.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(Писатель, Копия, НазначениеТипаXML.Явное);
Если Писатель.Закрыть() <> Текст Тогда
    ВызватьИсключение "Полный typed XML roundtrip нестабилен; ключ не допускается к setter";
КонецЕсли;
Возврат Текст;
КонецФункции
&НаСервере
Процедура ПроверитьСвоиКлючи()
ПроверитьУчебнуюСреду();
Если ЭтаФорма.ПользовательОпытов <> ИмяПользователя() Или ЭтаФорма.ПользовательОпытов = "" Тогда
    ВызватьИсключение "Изменился собственный именованный пользователь";
КонецЕсли;
Если ЭтаФорма.ОбластьКлючей = "" Или ЭтаФорма.ПрефиксКлючей <> "УчебныеПакеты85_" + ЭтаФорма.ОбластьКлючей + "_" Тогда
    ВызватьИсключение "Повреждён собственный namespace ключей";
КонецЕсли;
Для Каждого Ключ Из СтрРазделить(ЭтаФорма.КлючА + "," + ЭтаФорма.КлючБ + "," + ЭтаФорма.КлючБазы, ",") Цикл
    Если Ключ <> "" И Лев(Ключ, СтрДлина(ЭтаФорма.ПрефиксКлючей)) <> ЭтаФорма.ПрефиксКлючей Тогда
        ВызватьИсключение "Обнаружен ключ вне созданного namespace";
    КонецЕсли;
КонецЦикла;
КонецПроцедуры

&НаСервере
Функция ПолучитьКвитанциюОчистки() Экспорт
ПроверитьСвоиКлючи();
Возврат Новый Структура("Объект,Область,Префикс,Пользователь,КлючА,КлючБ,КлючБазы,СозданА,СозданБ,СозданБаза,ОчиститьА,ОчиститьБ,ОчиститьБазу", "Отчет.УчебныеСохраненныеВарианты85", ЭтаФорма.ОбластьКлючей, ЭтаФорма.ПрефиксКлючей, ЭтаФорма.ПользовательОпытов, ЭтаФорма.КлючА, ЭтаФорма.КлючБ, ЭтаФорма.КлючБазы, ЭтаФорма.СозданА, ЭтаФорма.СозданБ, ЭтаФорма.СозданБаза, ЭтаФорма.ОчиститьА, ЭтаФорма.ОчиститьБ, ЭтаФорма.ОчиститьБазу);
КонецФункции
&НаСервере
Процедура ПриКомпоновкеРезультата(СтандартнаяОбработка)
СтандартнаяОбработка = Истина;
ЭтаФорма.МаршрутКомпоновки = Ложь;
ЭтаФорма.СобытийДо = ЭтаФорма.СобытийДо + 1;
КонецПроцедуры

&НаСервере
Процедура ПослеКомпоновкиРезультата(Результат, СтандартнаяОбработка)
СтандартнаяОбработка = Истина;
ЭтаФорма.СобытийПосле = ЭтаФорма.СобытийПосле + 1;
Если ТипЗнч(Результат) <> Тип("ТабличныйДокумент") Тогда
    ВызватьИсключение "Событие формы не передало фактический ТабличныйДокумент";
КонецЕсли;
ЭтаФорма.МаршрутКомпоновки = Истина;
КонецПроцедуры

&НаКлиенте
Процедура СформироватьДляРучнойСверки()
До = ЭтаФорма.СобытийДо;
После = ЭтаФорма.СобытийПосле;
ЭтаФорма.МаршрутКомпоновки = Ложь;
ЭтаФорма.СкомпоноватьРезультат(РежимКомпоновкиРезультата.Непосредственно);
Если Не ЭтаФорма.МаршрутКомпоновки Или ЭтаФорма.СобытийДо <> До + 1 Или ЭтаФорма.СобытийПосле <> После + 1 Тогда
    ВызватьИсключение "Не подтверждён маршрут событий формы";
КонецЕсли;
Сообщить("Подтверждён только маршрут компоновки. Строки, поля и числа actual результата проверьте вручную");
КонецПроцедуры

&НаСервере
Процедура СохранитьИПроверитьСвоиВарианты()
ПроверитьСвоиКлючи();
Если ЭтаФорма.СозданА Или ЭтаФорма.СозданБ Или ЭтаФорма.ОчиститьА Или ЭтаФорма.ОчиститьБ Тогда
    ВызватьИсключение "Повторное Save запрещено: завершите этот опыт и точечную очистку через пульт";
КонецЕсли;
ЭтаФорма.ХранилищеПодтверждено = Ложь;
Попытка
ОбъектОтчета = ЭтаФорма.РеквизитФормыВЗначение("Отчет");
Схема = ОбъектОтчета.СхемаКомпоновкиДанных;
ЭтаФорма.XMLА = ПолныйТипизированныйXML(Схема.ВариантыНастроек.Получить(0).Настройки);
ЭтаФорма.XMLБ = ПолныйТипизированныйXML(Схема.ВариантыНастроек.Получить(1).Настройки);
Хранилище = ПолучитьСтандартноеХранилищеВариантовОтчетов();
Объект = "Отчет.УчебныеСохраненныеВарианты85";
Если Хранилище.Загрузить(Объект, ЭтаФорма.КлючА, , ЭтаФорма.ПользовательОпытов) <> Неопределено Или Хранилище.Загрузить(Объект, ЭтаФорма.КлючБ, , ЭтаФорма.ПользовательОпытов) <> Неопределено Тогда
    ВызватьИсключение "Save остановлен: один из новых ключей уже существует";
КонецЕсли;
Описание = Новый ОписаниеНастроек;
Описание.Представление = "Сохранённый подробный пакет85";
ЭтаФорма.ОчиститьА = Истина;
Хранилище.Сохранить(Объект, ЭтаФорма.КлючА, Схема.ВариантыНастроек.Получить(0).Настройки, Описание, ЭтаФорма.ПользовательОпытов);
ЭтаФорма.СозданА = Истина;
ПроверитьЗаписанныйВариант(Хранилище, ЭтаФорма.КлючА, ЭтаФорма.XMLА, "Сохранённый подробный пакет85");
Описание.Представление = "Сохранённый краткий пакет85";
ЭтаФорма.ОчиститьБ = Истина;
Хранилище.Сохранить(Объект, ЭтаФорма.КлючБ, Схема.ВариантыНастроек.Получить(1).Настройки, Описание, ЭтаФорма.ПользовательОпытов);
ЭтаФорма.СозданБ = Истина;
ПроверитьЗаписанныйВариант(Хранилище, ЭтаФорма.КлючБ, ЭтаФорма.XMLБ, "Сохранённый краткий пакет85");
ЭтаФорма.ХранилищеПодтверждено = Истина;
Исключение
    ЭтаФорма.ХранилищеПодтверждено = Ложь;
    ЭтаФорма.СостояниеУрока = "Save/readback остановлен: " + ОписаниеОшибки() + ". Нормальный серверный возврат сохраняет отметки завершённых Save для квитанции";
    ЭтаФорма.СостояниеУрока = ЭтаФорма.СостояниеУрока + СтрШаблон(". Свои pending ключи: %1 [%2], %3 [%4]; очистка ещё не подтверждена", ЭтаФорма.КлючА, ЭтаФорма.ОчиститьА, ЭтаФорма.КлючБ, ЭтаФорма.ОчиститьБ);
КонецПопытки;
КонецПроцедуры

&НаСервере
Процедура ПроверитьЗаписанныйВариант(Хранилище, Ключ, ОжидаемыйXML, Представление)
Описание = Новый ОписаниеНастроек;
Прочитано = Хранилище.Загрузить("Отчет.УчебныеСохраненныеВарианты85", Ключ, Описание, ЭтаФорма.ПользовательОпытов);
Если Прочитано = Неопределено Тогда
    ВызватьИсключение "После Save запись не найдена; setter запрещён";
КонецЕсли;
Если ПолныйТипизированныйXML(Прочитано) <> ОжидаемыйXML Или ТипЗнч(Описание.Представление) <> Тип("Строка") Или Описание.Представление <> Представление Тогда
    ВызватьИсключение "Не совпали полный typed payload или описание сохранённого варианта";
КонецЕсли;
КонецПроцедуры

&НаСервере
Процедура ЗагрузитьСвойСохраненныйВариант(Краткий)
ПроверитьСвоиКлючи();
Если Не ЭтаФорма.ХранилищеПодтверждено Тогда
    ВызватьИсключение "Сначала Save+Load+полное typed сравнение обоих вариантов";
КонецЕсли;
Ключ = ?(Краткий, ЭтаФорма.КлючБ, ЭтаФорма.КлючА);
Представление = ?(Краткий, "Сохранённый краткий пакет85", "Сохранённый подробный пакет85");
ПроверитьЗаписанныйВариант(ПолучитьСтандартноеХранилищеВариантовОтчетов(), Ключ, ?(Краткий, ЭтаФорма.XMLБ, ЭтаФорма.XMLА), Представление);
ЭтаФорма.УстановитьТекущийВариант(Ключ);
Если ТипЗнч(ЭтаФорма.КлючТекущегоВарианта) <> Тип("Строка") Или ЭтаФорма.КлючТекущегоВарианта <> Ключ Или ТипЗнч(ЭтаФорма.ПредставлениеТекущегоВарианта) <> Тип("Строка") Или ЭтаФорма.ПредставлениеТекущегоВарианта <> Представление Тогда
    ВызватьИсключение "Setter не подтвердил реальный ключ и сохранённое представление";
КонецЕсли;
ОбъектОтчета = ЭтаФорма.РеквизитФормыВЗначение("Отчет");
Если ПолныйТипизированныйXML(ОбъектОтчета.КомпоновщикНастроек.Настройки) <> ?(Краткий, ЭтаФорма.XMLБ, ЭтаФорма.XMLА) Тогда
    ВызватьИсключение "В actual основных настройках формы изменился полный сохранённый вариант";
КонецЕсли;
ПроверитьПолныйВыбор(ОбъектОтчета.КомпоновщикНастроек.ПолучитьНастройки(), ?(Краткий, "Пакет,Сумма", "Пакет,Количество,Сумма"));
ЭтаФорма.СостояниеУрока = "Подтверждены Save/Load, setter и полный effective выбор: " + Представление;
КонецПроцедуры

&НаКлиенте
Процедура СоздатьСвоиВарианты(Команда)
Попытка
    СохранитьИПроверитьСвоиВарианты();
    Если Не ЭтаФорма.ХранилищеПодтверждено Тогда
        ВызватьИсключение ЭтаФорма.СостояниеУрока;
    КонецЕсли;
    ЗагрузитьСвойСохраненныйВариант(Ложь);
    СформироватьДляРучнойСверки();
Исключение
    ЭтаФорма.МаршрутКомпоновки = Ложь;
    ЭтаФорма.СостояниеУрока = "Создание остановлено: " + ОписаниеОшибки() + ". Созданные записи учтены для точечной очистки";
КонецПопытки;
Сообщить(ЭтаФорма.СостояниеУрока);
КонецПроцедуры

&НаКлиенте
Процедура ВыбратьКраткий(Команда)
Попытка
    ЗагрузитьСвойСохраненныйВариант(Истина);
    СформироватьДляРучнойСверки();
Исключение
    ЭтаФорма.МаршрутКомпоновки = Ложь;
    ЭтаФорма.СостояниеУрока = "Краткий вариант не подтверждён: " + ОписаниеОшибки();
КонецПопытки;
Сообщить(ЭтаФорма.СостояниеУрока);
КонецПроцедуры

&НаКлиенте
Процедура ВернутьПодробный(Команда)
Попытка
    ЗагрузитьСвойСохраненныйВариант(Ложь);
    СформироватьДляРучнойСверки();
Исключение
    ЭтаФорма.МаршрутКомпоновки = Ложь;
    ЭтаФорма.СостояниеУрока = "Подробный вариант не подтверждён: " + ОписаниеОшибки();
КонецПопытки;
Сообщить(ЭтаФорма.СостояниеУрока);
КонецПроцедуры
Полный независимый пульт и точечная очистка

Модуль общей управляемой формы ПультСохраненныхВариантов85

Смешанный управляемый: толстый клиент и сервер

Перем РабочаяФорма;
Перем КвитанцияОчистки;

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

&НаСервереБезКонтекста
Процедура ПроверитьУчебнуюСреду()
Если ИмяПользователя() <> "АвторВариантов85" Тогда
    ВызватьИсключение "Нужен отдельный новый именованный пользователь АвторВариантов85";
КонецЕсли;
Если КлиентскоеПриложение.ТекущийВариантИнтерфейса() <> ВариантИнтерфейсаКлиентскогоПриложения.Такси Тогда
    ВызватьИсключение "Нужен собственный толстый управляемый сеанс Такси";
КонецЕсли;
КонецПроцедуры

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

&НаКлиенте
Процедура ЗакрытьИУдалитьСозданное(Команда)
Попытка
    Если КвитанцияОчистки = Неопределено Тогда
        Если РабочаяФорма = Неопределено Тогда
            ВызватьИсключение "Нет собственного экземпляра отчёта";
        КонецЕсли;
        Если Не РабочаяФорма.Открыта() Тогда
            ВызватьИсключение "Отчёт закрыли до получения квитанции; автоматическое удаление запрещено";
        КонецЕсли;
        КвитанцияОчистки = РабочаяФорма.ПолучитьКвитанциюОчистки();
    КонецЕсли;
    Если РабочаяФорма.Открыта() Тогда
        РабочаяФорма.Закрыть();
    КонецЕсли;
    Если РабочаяФорма.Открыта() Тогда
        ВызватьИсключение "Собственная форма ещё открыта; удаление запрещено";
    КонецЕсли;
    УдалитьПоСобственнойКвитанции(КвитанцияОчистки);
    РабочаяФорма = Неопределено;
    КвитанцияОчистки = Неопределено;
    Сообщить("Проверено отсутствие только своих pending/созданных записей после точечного Delete и readback. Системные текущие ключи, история и весь профиль не очищались");
Исключение
    Сообщить("Очистка не подтверждена: " + ОписаниеОшибки() + ". Квитанция сохранена для повторной узкой попытки, чужие записи не выбираются");
    Если КвитанцияОчистки <> Неопределено Тогда
        Сообщить(СтрШаблон("Непроверенная очистка своего объекта %1 пользователя %2: А=%3 pending=%4; Б=%5 pending=%6; база=%7 pending=%8", КвитанцияОчистки.Объект, КвитанцияОчистки.Пользователь, КвитанцияОчистки.КлючА, КвитанцияОчистки.ОчиститьА, КвитанцияОчистки.КлючБ, КвитанцияОчистки.ОчиститьБ, КвитанцияОчистки.КлючБазы, КвитанцияОчистки.ОчиститьБазу));
    Иначе
        Сообщить("Квитанция ещё не получена: автоматическое удаление не выполнялось. В собственном отчёте проверьте показанные pending ключи; не объявляйте опыт завершённым");
    КонецЕсли;
КонецПопытки;
КонецПроцедуры

&НаСервереБезКонтекста
Процедура УдалитьПоСобственнойКвитанции(Квитанция)
ПроверитьУчебнуюСреду();
Если ТипЗнч(Квитанция) <> Тип("Структура") Тогда
    ВызватьИсключение "Нужна квитанция реального собственного Save";
КонецЕсли;
Если Квитанция.Объект <> "Отчет.УчебныеСохраненныеВарианты85" Или Квитанция.Пользователь <> ИмяПользователя() Или Квитанция.Пользователь = "" Или Квитанция.Область = "" Тогда
    ВызватьИсключение "Квитанция не принадлежит собственным отчёту, сеансу и пользователю";
КонецЕсли;
Если Квитанция.Префикс <> "УчебныеПакеты85_" + Квитанция.Область + "_" Или Квитанция.КлючА <> Квитанция.Префикс + "А" Или Квитанция.КлючБ <> Квитанция.Префикс + "Б" Тогда
    ВызватьИсключение "Квитанция содержит ключ вне выделенного namespace";
КонецЕсли;
Если ТипЗнч(Квитанция.СозданА) <> Тип("Булево") Или ТипЗнч(Квитанция.СозданБ) <> Тип("Булево") Или ТипЗнч(Квитанция.СозданБаза) <> Тип("Булево") Тогда
    ВызватьИсключение "Повреждены отметки завершённого Save";
КонецЕсли;
Если ТипЗнч(Квитанция.ОчиститьА) <> Тип("Булево") Или ТипЗнч(Квитанция.ОчиститьБ) <> Тип("Булево") Или ТипЗнч(Квитанция.ОчиститьБазу) <> Тип("Булево") Тогда
    ВызватьИсключение "Повреждены отметки возможной записи собственных pending ключей";
КонецЕсли;
Если (Квитанция.СозданА И Не Квитанция.ОчиститьА) Или (Квитанция.СозданБ И Не Квитанция.ОчиститьБ) Или (Квитанция.СозданБаза И Не Квитанция.ОчиститьБазу) Тогда
    ВызватьИсключение "У завершённого Save потеряна запись собственного ownership для cleanup";
КонецЕсли;
Если Квитанция.КлючБазы <> "" Или Квитанция.СозданБаза Или Квитанция.ОчиститьБазу Тогда
    ВызватьИсключение "В опыте вариантов не должно быть записи базы профилей";
КонецЕсли;
Хранилище = ПолучитьСтандартноеХранилищеВариантовОтчетов();
Если Квитанция.ОчиститьА Тогда
    УдалитьТолькоСозданнуюЗапись(Хранилище, Квитанция.Объект, Квитанция.КлючА, Квитанция.Пользователь, Квитанция.Префикс);
КонецЕсли;
Если Квитанция.ОчиститьБ Тогда
    УдалитьТолькоСозданнуюЗапись(Хранилище, Квитанция.Объект, Квитанция.КлючБ, Квитанция.Пользователь, Квитанция.Префикс);
КонецЕсли;
КонецПроцедуры

&НаСервереБезКонтекста
Процедура УдалитьТолькоСозданнуюЗапись(Хранилище, Объект, Ключ, Пользователь, Префикс)
Если ТипЗнч(Объект) <> Тип("Строка") Или ТипЗнч(Ключ) <> Тип("Строка") Или ТипЗнч(Пользователь) <> Тип("Строка") Тогда
    ВызватьИсключение "Удалить требует три конкретные строки";
КонецЕсли;
Если Объект = "" Или Ключ = "" Или Пользователь = "" Или Пользователь <> ИмяПользователя() Или Лев(Ключ, СтрДлина(Префикс)) <> Префикс Тогда
    ВызватьИсключение "Широкое удаление или чужой ключ запрещены";
КонецЕсли;
Хранилище.Удалить(Объект, Ключ, Пользователь);
Если Хранилище.Загрузить(Объект, Ключ, , Пользователь) <> Неопределено Тогда
    ВызватьИсключение "После точечного Удалить readback всё ещё нашёл запись";
КонецЕсли;
КонецПроцедуры
Полный запуск собственного стенда

Модуль управляемого приложения новой конфигурации УчебныеВариантыПакетов85; событие ПриНачалеРаботыСистемы

Толстый клиент, управляемое приложение

Процедура ПриНачалеРаботыСистемы()
ОткрытьФорму("ОбщаяФорма.ПультСохраненныхВариантов85", , , Новый УникальныйИдентификатор);
КонецПроцедуры

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

  1. Подготовьте новую базу, именованного пользователя, право СохранениеДанныхПользователя, report-форму, отдельный пульт и полный запуск. Ни один из этих блоков здесь не исполнялся.

  2. Откройте отчёт исключительно кнопкой пульта. ПриСоздании строит свою схему и генерирует новый строковый namespace; сгенерированные строки пока не считаются существующими вариантами.

  3. Нажмите СоздатьСвоиВарианты. До записи код получает полный XML обоих actual объектов, typed roundtrip требует тождественный XML; неканоническая или неподдержанная сериализация даёт отказ, не ложный успех.

  4. Load обоих новых ключей до Save должен вернуть Неопределено. Иначе ничего не перезаписывается. Native object namespace: ровно Отчет.УчебныеСохраненныеВарианты85.

  5. Оба успешных Save фиксируются до readback; Load должен восстановить НастройкиКомпоновкиДанных, весь сериализованный объект и своё описание. Только затем разрешается setter с КлючА.

  6. Форма должна показать actual ключ/представление подробного варианта; effective выбор — Пакет,Количество,Сумма. После штатной компоновки вручную сверяйте три реальные строки А/3/60, Б/1/20, В/6/120.

  7. Нажмите ВыбратьКраткий: повторный readback до setter, затем actual КлючБ/описание и полный effective выбор Пакет,Сумма. В actual выводе вручную сверяйте А/60, Б/20, В/120.

  8. Нажмите ВернутьПодробный: повторите A-key, представление, три effective поля и ручную сверку actual результата. Не интерпретируйте изменение ключа как числовое доказательство.

  9. Вернитесь в независимый пульт и нажмите ЗакрытьИУдалитьСозданное. Он получает квитанцию только своей формы, закрывает её, требует Открыта()=Ложь и удаляет только отмеченные pending ключи А/Б собственных Save-попыток; readback каждого — Неопределено. Возможная частичная запись при исключении Save тоже остаётся в квитанции.

  10. При частичной ошибке cleanup квитанция не сбрасывается: можно повторить ту же узкую очистку. Не запускайте новый опыт до её завершения и не передавайте произвольные ключи.

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

  1. Порядок Save(object,key,value,description,user) и Load(object,key,outputDescription,user) совпадает с HBK.

  2. До каждого setter есть actual readback + полный typed payload + описание; UUID сам по себе не разрешает setter.

  3. XML используется только для типа Settings, для которого native прямо разрешает XML/XDTO; нет записи файла, строки не нормализуются ради успеха.

  4. Actual ключ/представление и полный effective выбор проверены; маршрут событий не выдаётся за правильность числа.

  5. Пульт отдельно закрывает свой экземпляр и проверяет Открыта до Delete с тремя непустыми string-аргументами.

  6. Очистка разрешена только отмеченным pending ключам своих Save-попыток, отсутствовавшим перед Save; actual завершённый Save и разрешённый после typed readback ключ — отдельные состояния. Readback после cleanup должен вернуть Неопределено.

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

Будущий проверенный путь: две реальные собственные записи → A/B/A report-setter → ручная сверка actual выводов → закрытие собственного экземпляра → Delete только A/B с отсутствием при readback. Здесь это только подготовленный код; runtime0.

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

  1. Сохраняющий сценарий допустим только в совершенно новой отдельной базе/у нового именованного пользователя; не запускайте его в рабочей базе.

  2. Метаданные хранилищ должны быть незаданы; стандартный менеджер и отчётная форма иначе могут использовать разные хранилища.

  3. Полный XML сравнивает сериализованное состояние Settings, а не доступные поля/кэш редактора. Native не обещает canonical XML: нестабильность означает отказ до setter, не обрезанное сравнение.

  4. Setter также загружает пользовательские настройки, использованные с вариантом последними. Новый собственный ключ и отсутствие других действий — необходимое ограничение стенда.

  5. Не проверяем и не обещаем автоматическое изменение ВариантМодифицирован/ПользовательскиеНастройкиМодифицированы.

  6. Не закрывайте отчёт вручную и не изменяйте квитанцию: восстановление ownership чужого/старого закрытого экземпляра не предусмотрено.

  7. Системные текущие ключи и last-user-settings платформа может писать сама; Delete двух собственных записей не очищает всю историю или профиль.

  8. Ни одного Удалить с Неопределено или пустым пользовательским именем: каждый такой аргумент расширил бы удаление.

  9. Флаги и effective выбор не доказывают числовой или визуальный результат; необходим будущий полный ручной протокол actual документа.

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

Два собственных профиля границ: настоящий вариант, полный user-состав и effective 0..9↔2..3

Минимальный профиль собственного отчёта содержит только Минимум/Максимум с реальными ID и представлениями основных настроек, оба числа — явные qualifiers1,0 неотрицательные и 0<=Минимум<=Максимум<=9. После Save/Load всего базового Settings и полного структурного typed состава обоих user-профилей разрешаются реальные report-setters. Сохранённая база остаётся прежней, effective границы меняются. Числа и строки actual результата сверяются отдельно вручную. Здесь никаких внутренних записей и запуска1С не было.

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

Смешанный управляемый: толстый клиент 8.5.1.1343 Такси и сервер

Подготовка

  1. Только будущий ручной опыт: создайте совершенно новую пустую учебную информационную базу. Здесь 1С и BSL не запускались; runtime-проверок 0. Не переносите урок в рабочую конфигурацию.

  2. В конфигураторе имя собственной конфигурации задайте УчебныеВариантыПакетов85; основное приложение — управляемое, Режим совместимости — Не использовать. Запуск: толстый клиент в режиме управляемого приложения, установленная платформа ровно 8.5.1.1343, интерфейс Такси, обычный режим основного окна. Обычный режим основного окна не означает обычное приложение: приложение остаётся управляемым. Проверки версии/имени/интерфейса не доказывают, каким исполняемым клиентом был запущен сеанс: проверьте способ запуска вручную.

  3. Создайте нового отдельного пользователя АвторВариантов85 только в этой новой базе. Не переименовывайте и не используйте рабочего пользователя. Сеанс всегда запускайте им: guard проверяет точное ИмяПользователя().

  4. Создайте собственную роль ПакетыУчебные85: доступ только к своему отчёту УчебныеГраницыПакетов85, его собственной форме и своему общему пульту, просмотр/использование форм. В правах корня конфигурации включите ТолстыйКлиент (ThickClient), РежимОсновногоОкнаОбычный (MainWindowModeNormal) и СохранениеДанныхПользователя (SaveUserData). После обновления конфигурации базы данных назначьте эту роль новому пользователю АвторВариантов85. Не выдавайте учебному пользователю Администрирование, АдминистрированиеДанных или ОбновлениеКонфигурацииБазыДанных. Отчёт не требует чтения или записи предметных объектов; локальный запрос состоит только из трёх константных строк.

  5. У конфигурации свойства ХранилищеВариантовОтчетов и ХранилищеПользовательскихНастроекОтчетов оставьте незаданными. Это необходимое соответствие стандартному внутреннему хранилищу, которое получает авторский код; при собственном прикладном хранилище отчётный setter мог бы читать другое место.

  6. Метаданные → Отчёты: создайте собственный УчебныеГраницыПакетов85. ОсновнаяСхемаКомпоновкиДанных в метаданных не нужна: полный модуль строит собственную схему в памяти и присваивает реальному ОтчетОбъект.СхемаКомпоновкиДанных. Никаких таблиц базы и внешних наборов нет.

  7. В УчебныеГраницыПакетов85 → Формы создайте управляемую форму отчёта ПрофилиГраниц85 типа Основная. Не обычную форму. Укажите её основной формой отчёта.

  8. Основной реквизит формы Отчет — ОтчетОбъект.УчебныеГраницыПакетов85, флаг Основной. Реквизит Результат — ТабличныйДокумент. Элемент ПолеРезультата — поле табличного документа, ПутьКДанным = Результат. Имена собственные, не предполагаются имена автоматически созданных элементов.

  9. Добавьте реквизиты формы СостояниеУрока (Строка неограниченная), МаршрутКомпоновки (Булево), СобытийДо и СобытийПосле (Число 9,0 неотрицательное). Счётчики относятся только к маршруту событий, не к строкам или числам отчёта. Добавьте поле состояния с ПутьКДанным = СостояниеУрока.

  10. В событиях именно формы назначьте ПриСозданииНаСервере → ПриСозданииНаСервере, ПриКомпоновкеРезультата → ПриКомпоновкеРезультата, ПослеКомпоновкиРезультата → ПослеКомпоновкиРезультата. Не создавайте эти обработчики в модуле объекта отчёта; его одноимённые события имеют другой контракт.

  11. Создайте собственные команды формы и кнопки с действиями: СоздатьСвоиПрофили → СоздатьСвоиПрофили; УзкиеГраницы → УзкиеГраницы; ВернутьВсе → ВернутьВсе. Все имена обработчиков приведены в основном полном модуле. Штатные произвольные кнопки сохранения/загрузки не используйте в этом опыте.

  12. Точное место основного блока: модуль управляемой формы Отчет.УчебныеГраницыПакетов85.Форма.ПрофилиГраниц85. Замените только модуль своей новой формы целиком, не добавляйте неизвестные общие модули и helpers.

  13. Вся схема задаётся основным блоком: источник ИсточникПакетов85 типа Local, набор запроса Пакеты85 с АвтоЗаполнениеДоступныхПолей = Истина; Пакет (Строка), Количество (Число) и Сумма (Число) образуются константным запросом ПакетА/3/60, ПакетБ/1/20, ПакетВ/6/120. Детальные записи без промежуточных или общего итога. Поля выбора Подробно85: Пакет,Количество,Сумма; Кратко85: Пакет,Сумма.

  14. Не привязывайте пригодность схемы или числовую правильность результата к служебному флагу. ПослеКомпоновкиРезультата проверяет только actual тип параметра ТабличныйДокумент и маршрут штатной компоновки. Координаты вывода не предполагаются: полный состав реальных строк и значения читатель проверит в ПолеРезультата вручную.

  15. Добавьте реквизит XMLБазы (Строка неограниченная); полный typed XML-снимок только своего базового Settings. Параметры задаёт авторский модуль: дополнительных form-параметров и пользовательского ручного числового ввода нет.

  16. Метаданные → Общие формы: создайте управляемую ПультПрофилейГраниц85 без основного реквизита и предметных данных. Команды/кнопки ОткрытьСвойОтчет → ОткрытьСвойОтчет и ЗакрытьИУдалитьСозданное → ЗакрытьИУдалитьСозданное. Событие ПриСозданииНаСервере назначьте одноимённому обработчику. Точное место supporting-блока: модуль общей управляемой формы ПультПрофилейГраниц85; вставьте полный блок именно туда целиком.

  17. Пульт держит только свой реальный экземпляр РабочаяФорма, полученный с новым УникальныйИдентификатор в четвёртом аргументе ПолучитьФорму. Не открывайте второй отчёт с теми же ключами, не перезапускайте пульт до cleanup и не изменяйте профили через другие формы.

  18. Полный supporting-блок запуска вставьте в модуль управляемого приложения этой новой пустой конфигурации; ПриНачалеРаботыСистемы вызывает только ОбщаяФорма.ПультПрофилейГраниц85. Для разных уроков запускайте соответствующий полный блок, не три обработчика одинакового имени сразу.

  19. В форме добавьте реквизиты Строка неограниченная: ПользовательОпытов, ОбластьКлючей, ПрефиксКлючей, КлючА, КлючБ, КлючБазы; Булево: СозданА, СозданБ, СозданБаза, ОчиститьА, ОчиститьБ, ОчиститьБазу, ХранилищеПодтверждено. Сгенерированный UUID становится частью строкового namespace только для нового опыта; до фактических Save, Load и полного сравнения это не существующий вариант или профиль.

  20. Сохраняющий код выполняет внутренние записи настроек только при вашем будущем запуске в этой новой базе. Пять аргументов Save: объект, ключ, actual настройки, ОписаниеНастроек с представлением, captured current пользователь; четыре аргумента Load: объект, ключ, output описание, тот же пользователь. Неопределено после Load — отсутствие записи и отказ, не объект настроек.

  21. После precheck отсутствия собственного ключа, до вызова Save фиксируется Очистить* — ownership точного pending ключа; исключение Save не доказывает отсутствие возможной частичной записи. После нормально завершённого Save отдельно фиксируется Создан*. Только после всех typed readback разрешается ХранилищеПодтверждено. Ошибки Save/readback перехватываются внутри серверной процедуры с исходной диагностикой и нормальным возвратом формы; client False не продолжает setter. Квитанция сохраняет все точные pending ключи для узкой cleanup даже при сбое.

  22. Не закрывайте отчёт вручную. Полный supporting-блок пульта получает actual квитанцию у собственного экземпляра, закрывает его и требует Открыта() = Ложь до серверной очистки. Не изменяйте квитанцию и не передавайте в cleanup произвольную структуру; это узкий стенд одного собственного пользователя, не сервис удаления пользовательских ключей.

  23. Очистка удаляет только свои отмеченные pending ключи, отсутствовавшие перед собственным Save, включая возможную частичную запись при его исключении. Ровно три непустые строки: свой объект, свой ключ, свой current пользователь. Namespace и принадлежность квитанции проверяются до Delete; readback должен стать Неопределено. При сбое выводятся точные свои ключи/отметки, квитанция остаётся и очистка не объявляется завершённой. Системное хранилище, текущие ключи формы, историю и все настройки пользователя код не очищает.

  24. После всех подготовок метаданных, реквизитов, событий, команд, полных модулей формы/пульта/управляемого приложения и прав роли автор стенда в конфигураторе сохраняет конфигурацию и выполняет Конфигурация → Обновить конфигурацию базы данных (F7). Подтвердите обновление именно новой учебной базы. Это действие автора стенда, а не требование административных прав у учебного пользователя. После F7 проверьте назначение роли ПакетыУчебные85 пользователю АвторВариантов85 и только затем запускайте собственный управляемый сеанс этим пользователем.

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Попытка
    ПроверитьУчебнуюСреду();
    Если ЭтаФорма.ТипФормыОтчета <> ТипФормыОтчета.Основная Тогда
        ВызватьИсключение "Нужна собственная управляемая форма отчёта Основная";
    КонецЕсли;
    ЭтаФорма.РежимБлокировкиПриОткрытииОкна = РежимБлокировкиПриОткрытииОкнаФормы.НеБлокировать;
    ОбъектОтчета = ЭтаФорма.РеквизитФормыВЗначение("Отчет");
    ОбъектОтчета.СхемаКомпоновкиДанных = СоздатьСобственнуюСхему();
    ОбъектОтчета.КомпоновщикНастроек.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(ОбъектОтчета.СхемаКомпоновкиДанных));
    ОбъектОтчета.КомпоновщикНастроек.ЗагрузитьНастройки(ОбъектОтчета.СхемаКомпоновкиДанных.НастройкиПоУмолчанию);
    ЭтаФорма.ЗначениеВРеквизитФормы(ОбъектОтчета, "Отчет");
    ЭтаФорма.СобытийДо = 0;
    ЭтаФорма.СобытийПосле = 0;
    ЭтаФорма.МаршрутКомпоновки = Ложь;
    ЭтаФорма.СостояниеУрока = "Собственная схема готова; числа и внешний вид не проверены";
    ЭтаФорма.ПользовательОпытов = ИмяПользователя();
    ЭтаФорма.ОбластьКлючей = Строка(Новый УникальныйИдентификатор);
    ЭтаФорма.ПрефиксКлючей = "УчебныеПакеты85_" + ЭтаФорма.ОбластьКлючей + "_";
    ЭтаФорма.КлючА = ЭтаФорма.ПрефиксКлючей + "А";
    ЭтаФорма.КлючБ = ЭтаФорма.ПрефиксКлючей + "Б";
    ЭтаФорма.КлючБазы = "";
    ЭтаФорма.СозданА = Ложь;
    ЭтаФорма.СозданБ = Ложь;
    ЭтаФорма.СозданБаза = Ложь;
    ЭтаФорма.ОчиститьА = Ложь;
    ЭтаФорма.ОчиститьБ = Ложь;
    ЭтаФорма.ОчиститьБазу = Ложь;
    ЭтаФорма.ХранилищеПодтверждено = Ложь;
    ЭтаФорма.КлючБазы = ЭтаФорма.ПрефиксКлючей + "База";
    ЭтаФорма.XMLБазы = ПолныйТипизированныйXML(ОбъектОтчета.СхемаКомпоновкиДанных.НастройкиПоУмолчанию);
    ПроверитьОсновныеГраницы(ОбъектОтчета.КомпоновщикНастроек.Настройки, 0, 9);
Исключение
    Отказ = Истина;
    ВызватьИсключение "Подготовка остановлена: " + ОписаниеОшибки();
КонецПопытки;
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ПроверитьУчебнуюСреду()
Если ИмяПользователя() <> "АвторВариантов85" Тогда
    ВызватьИсключение "Нужен отдельный новый именованный пользователь АвторВариантов85";
КонецЕсли;
Если КлиентскоеПриложение.ТекущийВариантИнтерфейса() <> ВариантИнтерфейсаКлиентскогоПриложения.Такси Тогда
    ВызватьИсключение "Нужен собственный толстый управляемый сеанс Такси";
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция СоздатьСобственнуюСхему()
Схема = Новый СхемаКомпоновкиДанных;
Источник = Схема.ИсточникиДанных.Добавить();
Источник.Имя = "ИсточникПакетов85";
Источник.ТипИсточникаДанных = "Local";
Набор = Схема.НаборыДанных.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
Набор.Имя = "Пакеты85";
Набор.ИсточникДанных = Источник.Имя;
Набор.АвтоЗаполнениеДоступныхПолей = Истина;
Набор.Запрос = "ВЫБРАТЬ Пакеты.Пакет, Пакеты.Количество, Пакеты.Сумма
|ИЗ
|    (ВЫБРАТЬ ""ПакетА"" КАК Пакет, 3 КАК Количество, 60 КАК Сумма
|    ОБЪЕДИНИТЬ ВСЕ
|    ВЫБРАТЬ ""ПакетБ"", 1, 20
|    ОБЪЕДИНИТЬ ВСЕ
|    ВЫБРАТЬ ""ПакетВ"", 6, 120) КАК Пакеты
|ГДЕ Пакеты.Количество >= &Минимум И Пакеты.Количество <= &Максимум";
Для Каждого ИмяГраницы Из СтрРазделить("Минимум,Максимум", ",") Цикл
    ПараметрСхемы = Схема.Параметры.Добавить();
    ПараметрСхемы.Имя = ИмяГраницы;
    ПараметрСхемы.Заголовок = "Учебная граница " + ИмяГраницы;
    ПараметрСхемы.ТипЗначения = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(1, 0, ДопустимыйЗнак.Неотрицательный));
    ПараметрСхемы.Значение = ?(ИмяГраницы = "Минимум", 0, 9);
    ПараметрСхемы.Использование = ИспользованиеПараметраКомпоновкиДанных.Всегда;
КонецЦикла;
Схема.ВариантыНастроек.Очистить();
Подробный = Схема.ВариантыНастроек.Добавить();
Подробный.Имя = "Подробно85";
Подробный.Представление = "Все три поля пакетов";
ЗаполнитьНастройки(Подробный.Настройки, "Пакет,Количество,Сумма");
Краткий = Схема.ВариантыНастроек.Добавить();
Краткий.Имя = "Кратко85";
Краткий.Представление = "Пакет и сумма";
ЗаполнитьНастройки(Краткий.Настройки, "Пакет,Сумма");
Возврат Схема;
КонецФункции

&НаСервереБезКонтекста
Процедура ЗаполнитьНастройки(Настройки, ИменаПолей)
Для Каждого ИмяПоля Из СтрРазделить(ИменаПолей, ",") Цикл
    Выбранное = Настройки.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
    Выбранное.Поле = Новый ПолеКомпоновкиДанных(ИмяПоля);
    Выбранное.Использование = Истина;
КонецЦикла;
Детали = Настройки.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
Детали.Использование = Истина;
АвтоВыбор = Детали.Выбор.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных"));
АвтоВыбор.Использование = Истина;
Для Каждого ИмяГраницы Из СтрРазделить("Минимум,Максимум", ",") Цикл
    Настройки.ПараметрыДанных.УстановитьЗначениеПараметра(ИмяГраницы, ?(ИмяГраницы = "Минимум", 0, 9));
    Граница = Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных(ИмяГраницы));
    Если Граница = Неопределено Тогда
        ВызватьИсключение "Не создан собственный параметр " + ИмяГраницы;
    КонецЕсли;
    Граница.Использование = Истина;
    Граница.ИдентификаторПользовательскойНастройки = "ГраницаПакетов85_" + ИмяГраницы;
    Граница.ПредставлениеПользовательскойНастройки = "Количество: " + ИмяГраницы;
    Граница.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Обычный;
КонецЦикла;
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ПроверитьПолныйВыбор(Настройки, ИменаПолей)
Если ТипЗнч(Настройки) <> Тип("НастройкиКомпоновкиДанных") Тогда
    ВызватьИсключение "Нет типизированных настроек выбора";
КонецЕсли;
Ожидаемые = СтрРазделить(ИменаПолей, ",");
Если Настройки.Выбор.Элементы.Количество() <> Ожидаемые.Количество() Тогда
    ВызватьИсключение "Изменился полный состав выбранных полей";
КонецЕсли;
Для Индекс = 0 По Ожидаемые.Количество() - 1 Цикл
    ПолеВыбора = Настройки.Выбор.Элементы.Получить(Индекс);
    Если ТипЗнч(ПолеВыбора) <> Тип("ВыбранноеПолеКомпоновкиДанных") Тогда
        ВызватьИсключение "В выборе появился неподдерживаемый элемент";
    КонецЕсли;
    Если ПолеВыбора.Поле <> Новый ПолеКомпоновкиДанных(Ожидаемые[Индекс]) Или ТипЗнч(ПолеВыбора.Использование) <> Тип("Булево") Или Не ПолеВыбора.Использование Тогда
        ВызватьИсключение "Не совпало поле или его использование";
    КонецЕсли;
КонецЦикла;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолныйТипизированныйXML(Настройки)
Если ТипЗнч(Настройки) <> Тип("НастройкиКомпоновкиДанных") Тогда
    ВызватьИсключение "Ожидался полный тип НастройкиКомпоновкиДанных";
КонецЕсли;
Писатель = Новый ЗаписьXML;
Писатель.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(Писатель, Настройки, НазначениеТипаXML.Явное);
Текст = Писатель.Закрыть();
Если ТипЗнч(Текст) <> Тип("Строка") Или Текст = "" Тогда
    ВызватьИсключение "Сериализация полного объекта не дала XML";
КонецЕсли;
Читатель = Новый ЧтениеXML;
Читатель.УстановитьСтроку(Текст);
Копия = СериализаторXDTO.ПрочитатьXML(Читатель, Тип("НастройкиКомпоновкиДанных"));
Читатель.Закрыть();
Если ТипЗнч(Копия) <> Тип("НастройкиКомпоновкиДанных") Тогда
    ВызватьИсключение "Полный XML не восстановил тип настроек";
КонецЕсли;
Писатель = Новый ЗаписьXML;
Писатель.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(Писатель, Копия, НазначениеТипаXML.Явное);
Если Писатель.Закрыть() <> Текст Тогда
    ВызватьИсключение "Полный typed XML roundtrip нестабилен; ключ не допускается к setter";
КонецЕсли;
Возврат Текст;
КонецФункции
&НаСервереБезКонтекста
Процедура ПроверитьСобственныеГраницы(Минимум, Максимум)
Если ТипЗнч(Минимум) <> Тип("Число") Или ТипЗнч(Максимум) <> Тип("Число") Тогда
    ВызватьИсключение "Обе границы должны оставаться числами";
КонецЕсли;
Если Минимум <> Цел(Минимум) Или Максимум <> Цел(Максимум) Или Минимум < 0 Или Минимум > Максимум Или Максимум > 9 Тогда
    ВызватьИсключение "Границы собственного опыта: целые 0 <= Минимум <= Максимум <= 9";
КонецЕсли;
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ПроверитьПолныйСобственныйПрофиль(Профиль, Минимум, Максимум)
ПроверитьСобственныеГраницы(Минимум, Максимум);
Если ТипЗнч(Профиль) <> Тип("ПользовательскиеНастройкиКомпоновкиДанных") Тогда
    ВызватьИсключение "Не получен тип ПользовательскиеНастройкиКомпоновкиДанных";
КонецЕсли;
Если Профиль.Элементы.Количество() <> 2 Или ТипЗнч(Профиль.ДополнительныеСвойства) <> Тип("Структура") Или Профиль.ДополнительныеСвойства.Количество() <> 0 Тогда
    ВызватьИсключение "Профиль не минимальный: требуется ровно два элемента и пустые дополнительные свойства";
КонецЕсли;
Дополнительные = Профиль.ДополнительныеНастройки;
Если ТипЗнч(Дополнительные) <> Тип("ПользовательскиеНастройкиКомпоновкиДанных") Тогда
    ВызватьИсключение "ДополнительныеНастройки не имеют документированного типа";
КонецЕсли;
Если Дополнительные.Элементы.Количество() <> 0 Или ТипЗнч(Дополнительные.ДополнительныеСвойства) <> Тип("Структура") Или Дополнительные.ДополнительныеСвойства.Количество() <> 0 Тогда
    ВызватьИсключение "В минимальном собственном профиле появились дополнительные настройки";
КонецЕсли;
Для Каждого ИмяГраницы Из СтрРазделить("Минимум,Максимум", ",") Цикл
    Идентификатор = "ГраницаПакетов85_" + ИмяГраницы;
    Элемент = Профиль.Элементы.Найти(Идентификатор);
    Если ТипЗнч(Элемент) <> Тип("ЗначениеПараметраНастроекКомпоновкиДанных") Тогда
        ВызватьИсключение "Нет единственного собственного элемента " + Идентификатор;
    КонецЕсли;
    Если ТипЗнч(Элемент.ИдентификаторПользовательскойНастройки) <> Тип("Строка") Или Элемент.ИдентификаторПользовательскойНастройки <> Идентификатор Тогда
        ВызватьИсключение "Изменился собственный ID элемента";
    КонецЕсли;
    Если ТипЗнч(Элемент.Значение) <> Тип("Число") Или Элемент.Значение <> ?(ИмяГраницы = "Минимум", Минимум, Максимум) Или ТипЗнч(Элемент.Использование) <> Тип("Булево") Или Не Элемент.Использование Тогда
        ВызватьИсключение "Не совпали полный тип, значение или использование элемента";
    КонецЕсли;
    Если ТипЗнч(Элемент.РежимОтображения) <> Тип("РежимОтображенияЭлементаНастройкиКомпоновкиДанных") Или Элемент.РежимОтображения <> РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Авто Тогда
        ВызватьИсключение "Не совпал полный typed режим user-профиля: нужен Авто, а не обещание интерфейса";
    КонецЕсли;
КонецЦикла;
Для Каждого Элемент Из Профиль.Элементы Цикл
    Если ТипЗнч(Элемент) <> Тип("ЗначениеПараметраНастроекКомпоновкиДанных") Тогда
        ВызватьИсключение "Профиль содержит неожиданный тип элемента";
    КонецЕсли;
    Если Элемент.ИдентификаторПользовательскойНастройки <> "ГраницаПакетов85_Минимум" И Элемент.ИдентификаторПользовательскойНастройки <> "ГраницаПакетов85_Максимум" Тогда
        ВызватьИсключение "Профиль содержит чужой ID";
    КонецЕсли;
КонецЦикла;
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ПроверитьОсновныеГраницы(Настройки, Минимум, Максимум, ПроверятьОсновнойРежим = Истина)
ПроверитьСобственныеГраницы(Минимум, Максимум);
Для Каждого ИмяГраницы Из СтрРазделить("Минимум,Максимум", ",") Цикл
    Граница = Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных(ИмяГраницы));
    Если ТипЗнч(Граница) <> Тип("ЗначениеПараметраНастроекКомпоновкиДанных") Тогда
        ВызватьИсключение "Не найден основной параметр " + ИмяГраницы;
    КонецЕсли;
    Если Граница.Параметр <> Новый ПараметрКомпоновкиДанных(ИмяГраницы) Или Граница.ИдентификаторПользовательскойНастройки <> "ГраницаПакетов85_" + ИмяГраницы Или Граница.ПредставлениеПользовательскойНастройки <> "Количество: " + ИмяГраницы Тогда
        ВызватьИсключение "Не совпали основное имя, ID или представление границы";
    КонецЕсли;
    Если ТипЗнч(Граница.Значение) <> Тип("Число") Или Граница.Значение <> ?(ИмяГраницы = "Минимум", Минимум, Максимум) Или ТипЗнч(Граница.Использование) <> Тип("Булево") Или Не Граница.Использование Тогда
        ВызватьИсключение "Не совпали effective числовая граница или её использование";
    КонецЕсли;
    Если ПроверятьОсновнойРежим Тогда
        Если ТипЗнч(Граница.РежимОтображения) <> Тип("РежимОтображенияЭлементаНастройкиКомпоновкиДанных") Или Граница.РежимОтображения <> РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Обычный Тогда
            ВызватьИсключение "Основной режим должен оставаться собственным Обычный; user Авто получает его из основной настройки, UI ещё не проверен";
        КонецЕсли;
    КонецЕсли;
КонецЦикла;
КонецПроцедуры

&НаСервереБезКонтекста
Функция СоздатьСобственныйПрофиль(Компоновщик, ОсновныеНастройки, Минимум, Максимум)
Компоновщик.ЗагрузитьНастройки(ОсновныеНастройки);
Профиль = Компоновщик.ПользовательскиеНастройки;
Для Каждого Элемент Из Профиль.Элементы Цикл
    Если ТипЗнч(Элемент) <> Тип("ЗначениеПараметраНастроекКомпоновкиДанных") Тогда
        ВызватьИсключение "В user-копии неожиданный тип: нормализовать чужой граф запрещено";
    КонецЕсли;
    Элемент.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Авто;
КонецЦикла;
ПроверитьПолныйСобственныйПрофиль(Профиль, 0, 9);
Профиль.Элементы.Найти("ГраницаПакетов85_Минимум").Значение = Минимум;
Профиль.Элементы.Найти("ГраницаПакетов85_Максимум").Значение = Максимум;
ПроверитьПолныйСобственныйПрофиль(Профиль, Минимум, Максимум);
Возврат Профиль;
КонецФункции
&НаСервере
Процедура ПроверитьСвоиКлючи()
ПроверитьУчебнуюСреду();
Если ЭтаФорма.ПользовательОпытов <> ИмяПользователя() Или ЭтаФорма.ПользовательОпытов = "" Тогда
    ВызватьИсключение "Изменился собственный именованный пользователь";
КонецЕсли;
Если ЭтаФорма.ОбластьКлючей = "" Или ЭтаФорма.ПрефиксКлючей <> "УчебныеПакеты85_" + ЭтаФорма.ОбластьКлючей + "_" Тогда
    ВызватьИсключение "Повреждён собственный namespace ключей";
КонецЕсли;
Для Каждого Ключ Из СтрРазделить(ЭтаФорма.КлючА + "," + ЭтаФорма.КлючБ + "," + ЭтаФорма.КлючБазы, ",") Цикл
    Если Ключ <> "" И Лев(Ключ, СтрДлина(ЭтаФорма.ПрефиксКлючей)) <> ЭтаФорма.ПрефиксКлючей Тогда
        ВызватьИсключение "Обнаружен ключ вне созданного namespace";
    КонецЕсли;
КонецЦикла;
КонецПроцедуры

&НаСервере
Функция ПолучитьКвитанциюОчистки() Экспорт
ПроверитьСвоиКлючи();
Возврат Новый Структура("Объект,Область,Префикс,Пользователь,КлючА,КлючБ,КлючБазы,СозданА,СозданБ,СозданБаза,ОчиститьА,ОчиститьБ,ОчиститьБазу", "Отчет.УчебныеГраницыПакетов85", ЭтаФорма.ОбластьКлючей, ЭтаФорма.ПрефиксКлючей, ЭтаФорма.ПользовательОпытов, ЭтаФорма.КлючА, ЭтаФорма.КлючБ, ЭтаФорма.КлючБазы, ЭтаФорма.СозданА, ЭтаФорма.СозданБ, ЭтаФорма.СозданБаза, ЭтаФорма.ОчиститьА, ЭтаФорма.ОчиститьБ, ЭтаФорма.ОчиститьБазу);
КонецФункции
&НаСервере
Процедура ПриКомпоновкеРезультата(СтандартнаяОбработка)
СтандартнаяОбработка = Истина;
ЭтаФорма.МаршрутКомпоновки = Ложь;
ЭтаФорма.СобытийДо = ЭтаФорма.СобытийДо + 1;
КонецПроцедуры

&НаСервере
Процедура ПослеКомпоновкиРезультата(Результат, СтандартнаяОбработка)
СтандартнаяОбработка = Истина;
ЭтаФорма.СобытийПосле = ЭтаФорма.СобытийПосле + 1;
Если ТипЗнч(Результат) <> Тип("ТабличныйДокумент") Тогда
    ВызватьИсключение "Событие формы не передало фактический ТабличныйДокумент";
КонецЕсли;
ЭтаФорма.МаршрутКомпоновки = Истина;
КонецПроцедуры

&НаКлиенте
Процедура СформироватьДляРучнойСверки()
До = ЭтаФорма.СобытийДо;
После = ЭтаФорма.СобытийПосле;
ЭтаФорма.МаршрутКомпоновки = Ложь;
ЭтаФорма.СкомпоноватьРезультат(РежимКомпоновкиРезультата.Непосредственно);
Если Не ЭтаФорма.МаршрутКомпоновки Или ЭтаФорма.СобытийДо <> До + 1 Или ЭтаФорма.СобытийПосле <> После + 1 Тогда
    ВызватьИсключение "Не подтверждён маршрут событий формы";
КонецЕсли;
Сообщить("Подтверждён только маршрут компоновки. Строки, поля и числа actual результата проверьте вручную");
КонецПроцедуры

&НаСервере
Процедура СохранитьСвоиПрофили()
ПроверитьСвоиКлючи();
ЭтаФорма.ХранилищеПодтверждено = Ложь;
Если ЭтаФорма.СозданА Или ЭтаФорма.СозданБ Или ЭтаФорма.СозданБаза Или ЭтаФорма.ОчиститьА Или ЭтаФорма.ОчиститьБ Или ЭтаФорма.ОчиститьБазу Тогда
    ВызватьИсключение "Повторное Save запрещено: используйте пульт очистки и новый экземпляр";
КонецЕсли;
Попытка
Объект = "Отчет.УчебныеГраницыПакетов85";
ХранилищеВариантов = ПолучитьСтандартноеХранилищеВариантовОтчетов();
ХранилищеПрофилей = ПолучитьСтандартноеХранилищеПользовательскихНастроекОтчетов();
ОбъектПрофилей = Объект + "/" + ЭтаФорма.КлючБазы;
Если ХранилищеВариантов.Загрузить(Объект, ЭтаФорма.КлючБазы, , ЭтаФорма.ПользовательОпытов) <> Неопределено Или ХранилищеПрофилей.Загрузить(ОбъектПрофилей, ЭтаФорма.КлючА, , ЭтаФорма.ПользовательОпытов) <> Неопределено Или ХранилищеПрофилей.Загрузить(ОбъектПрофилей, ЭтаФорма.КлючБ, , ЭтаФорма.ПользовательОпытов) <> Неопределено Тогда
    ВызватьИсключение "Обнаружена существующая запись; её нельзя перезаписывать";
КонецЕсли;
ОбъектОтчета = ЭтаФорма.РеквизитФормыВЗначение("Отчет");
Основные = ОбъектОтчета.СхемаКомпоновкиДанных.НастройкиПоУмолчанию;
ПроверитьОсновныеГраницы(Основные, 0, 9);
ПроверитьПолныйВыбор(Основные, "Пакет,Количество,Сумма");
Если ПолныйТипизированныйXML(Основные) <> ЭтаФорма.XMLБазы Тогда
    ВызватьИсключение "Базовый вариант изменился до сохранения";
КонецЕсли;
Все = СоздатьСобственныйПрофиль(ОбъектОтчета.КомпоновщикНастроек, Основные, 0, 9);
ПроверитьПолныйСобственныйПрофиль(Все, 0, 9);
Описание = Новый ОписаниеНастроек;
Описание.Представление = "База границ пакетов85";
ЭтаФорма.ОчиститьБазу = Истина;
ХранилищеВариантов.Сохранить(Объект, ЭтаФорма.КлючБазы, Основные, Описание, ЭтаФорма.ПользовательОпытов);
ЭтаФорма.СозданБаза = Истина;
ПроверитьЗаписаннуюБазу();
Описание.Представление = "Все количества 0..9";
ЭтаФорма.ОчиститьА = Истина;
ХранилищеПрофилей.Сохранить(ОбъектПрофилей, ЭтаФорма.КлючА, Все, Описание, ЭтаФорма.ПользовательОпытов);
ЭтаФорма.СозданА = Истина;
ПроверитьЗаписанныйПрофиль(ЭтаФорма.КлючА, 0, 9, "Все количества 0..9");
Узко = СоздатьСобственныйПрофиль(ОбъектОтчета.КомпоновщикНастроек, Основные, 2, 3);
ПроверитьПолныйСобственныйПрофиль(Узко, 2, 3);
Если ПолныйТипизированныйXML(Основные) <> ЭтаФорма.XMLБазы Тогда
    ВызватьИсключение "Создание user-копии изменило исходный базовый вариант";
КонецЕсли;
Описание.Представление = "Только количества 2..3";
ЭтаФорма.ОчиститьБ = Истина;
ХранилищеПрофилей.Сохранить(ОбъектПрофилей, ЭтаФорма.КлючБ, Узко, Описание, ЭтаФорма.ПользовательОпытов);
ЭтаФорма.СозданБ = Истина;
ПроверитьЗаписанныйПрофиль(ЭтаФорма.КлючБ, 2, 3, "Только количества 2..3");
ПроверитьЗаписаннуюБазу();
ЭтаФорма.ХранилищеПодтверждено = Истина;
Исключение
    ЭтаФорма.ХранилищеПодтверждено = Ложь;
    ЭтаФорма.СостояниеУрока = "Save/readback профилей остановлен: " + ОписаниеОшибки() + ". Нормальный серверный возврат сохраняет отметки завершённых Save для квитанции";
    ЭтаФорма.СостояниеУрока = ЭтаФорма.СостояниеУрока + СтрШаблон(". Свои pending ключи: %1 [%2], %3 [%4], база %5 [%6]; очистка ещё не подтверждена", ЭтаФорма.КлючА, ЭтаФорма.ОчиститьА, ЭтаФорма.КлючБ, ЭтаФорма.ОчиститьБ, ЭтаФорма.КлючБазы, ЭтаФорма.ОчиститьБазу);
КонецПопытки;
КонецПроцедуры

&НаСервере
Процедура ПроверитьЗаписаннуюБазу()
Описание = Новый ОписаниеНастроек;
База = ПолучитьСтандартноеХранилищеВариантовОтчетов().Загрузить("Отчет.УчебныеГраницыПакетов85", ЭтаФорма.КлючБазы, Описание, ЭтаФорма.ПользовательОпытов);
Если База = Неопределено Тогда
    ВызватьИсключение "Собственная база варианта после Save не найдена";
КонецЕсли;
Если ПолныйТипизированныйXML(База) <> ЭтаФорма.XMLБазы Или ТипЗнч(Описание.Представление) <> Тип("Строка") Или Описание.Представление <> "База границ пакетов85" Тогда
    ВызватьИсключение "Не совпали полный typed payload базы или её описание";
КонецЕсли;
ПроверитьОсновныеГраницы(База, 0, 9);
КонецПроцедуры

&НаСервере
Процедура ПроверитьЗаписанныйПрофиль(Ключ, Минимум, Максимум, Представление)
Описание = Новый ОписаниеНастроек;
Профиль = ПолучитьСтандартноеХранилищеПользовательскихНастроекОтчетов().Загрузить("Отчет.УчебныеГраницыПакетов85/" + ЭтаФорма.КлючБазы, Ключ, Описание, ЭтаФорма.ПользовательОпытов);
Если Профиль = Неопределено Тогда
    ВызватьИсключение "После Save собственный профиль не найден";
КонецЕсли;
ПроверитьПолныйСобственныйПрофиль(Профиль, Минимум, Максимум);
Если ТипЗнч(Описание.Представление) <> Тип("Строка") Или Описание.Представление <> Представление Тогда
    ВызватьИсключение "Не совпало сохранённое представление профиля";
КонецЕсли;
ПроверитьЗаписаннуюБазу();
КонецПроцедуры

&НаСервере
Процедура ПрименитьСвойПрофиль(Узкий)
ПроверитьСвоиКлючи();
Если Не ЭтаФорма.ХранилищеПодтверждено Тогда
    ВызватьИсключение "Нужны реальное Save/Load базы и обоих полностью проверенных профилей";
КонецЕсли;
Минимум = ?(Узкий, 2, 0);
Максимум = ?(Узкий, 3, 9);
Ключ = ?(Узкий, ЭтаФорма.КлючБ, ЭтаФорма.КлючА);
Представление = ?(Узкий, "Только количества 2..3", "Все количества 0..9");
ПроверитьЗаписанныйПрофиль(Ключ, Минимум, Максимум, Представление);
ЭтаФорма.УстановитьТекущийВариант(ЭтаФорма.КлючБазы);
Если ТипЗнч(ЭтаФорма.КлючТекущегоВарианта) <> Тип("Строка") Или ЭтаФорма.КлючТекущегоВарианта <> ЭтаФорма.КлючБазы Или ЭтаФорма.ПредставлениеТекущегоВарианта <> "База границ пакетов85" Тогда
    ВызватьИсключение "Не подтверждён настоящий сохранённый базовый вариант";
КонецЕсли;
ЭтаФорма.УстановитьТекущиеПользовательскиеНастройки(Ключ);
Если ТипЗнч(ЭтаФорма.КлючТекущихПользовательскихНастроек) <> Тип("Строка") Или ЭтаФорма.КлючТекущихПользовательскихНастроек <> Ключ Или ТипЗнч(ЭтаФорма.ПредставлениеТекущихПользовательскихНастроек) <> Тип("Строка") Или ЭтаФорма.ПредставлениеТекущихПользовательскихНастроек <> Представление Тогда
    ВызватьИсключение "Setter не подтвердил реальные ключ и представление профиля";
КонецЕсли;
Если ЭтаФорма.КлючТекущегоВарианта <> ЭтаФорма.КлючБазы Или ЭтаФорма.ПредставлениеТекущегоВарианта <> "База границ пакетов85" Тогда
    ВызватьИсключение "При выборе профиля неожиданно изменился базовый вариант";
КонецЕсли;
ОбъектОтчета = ЭтаФорма.РеквизитФормыВЗначение("Отчет");
Если ПолныйТипизированныйXML(ОбъектОтчета.КомпоновщикНастроек.Настройки) <> ЭтаФорма.XMLБазы Тогда
    ВызватьИсключение "При выборе user-профиля изменились полные actual основные настройки базового варианта";
КонецЕсли;
ПроверитьПолныйСобственныйПрофиль(ОбъектОтчета.КомпоновщикНастроек.ПользовательскиеНастройки, Минимум, Максимум);
ПроверитьОсновныеГраницы(ОбъектОтчета.КомпоновщикНастроек.Настройки, 0, 9);
ПроверитьОсновныеГраницы(ОбъектОтчета.КомпоновщикНастроек.ПолучитьНастройки(), Минимум, Максимум, Ложь);
ПроверитьПолныйВыбор(ОбъектОтчета.КомпоновщикНастроек.ПолучитьНастройки(), "Пакет,Количество,Сумма");
ПроверитьЗаписаннуюБазу();
ЭтаФорма.СостояниеУрока = "Подтверждены полный профиль, сохранённая база и effective границы " + Представление + "; это не доказательство строк и чисел результата";
КонецПроцедуры

&НаКлиенте
Процедура СоздатьСвоиПрофили(Команда)
Попытка
    СохранитьСвоиПрофили();
    Если Не ЭтаФорма.ХранилищеПодтверждено Тогда
        ВызватьИсключение ЭтаФорма.СостояниеУрока;
    КонецЕсли;
    ПрименитьСвойПрофиль(Ложь);
    СформироватьДляРучнойСверки();
Исключение
    ЭтаФорма.МаршрутКомпоновки = Ложь;
    ЭтаФорма.СостояниеУрока = "Создание профилей остановлено: " + ОписаниеОшибки() + ". Созданные записи учтены для точечной очистки";
КонецПопытки;
Сообщить(ЭтаФорма.СостояниеУрока);
КонецПроцедуры

&НаКлиенте
Процедура УзкиеГраницы(Команда)
Попытка
    ПрименитьСвойПрофиль(Истина);
    СформироватьДляРучнойСверки();
Исключение
    ЭтаФорма.МаршрутКомпоновки = Ложь;
    ЭтаФорма.СостояниеУрока = "Узкие границы не подтверждены: " + ОписаниеОшибки();
КонецПопытки;
Сообщить(ЭтаФорма.СостояниеУрока);
КонецПроцедуры

&НаКлиенте
Процедура ВернутьВсе(Команда)
Попытка
    ПрименитьСвойПрофиль(Ложь);
    СформироватьДляРучнойСверки();
Исключение
    ЭтаФорма.МаршрутКомпоновки = Ложь;
    ЭтаФорма.СостояниеУрока = "Возврат всех границ не подтверждён: " + ОписаниеОшибки();
КонецПопытки;
Сообщить(ЭтаФорма.СостояниеУрока);
КонецПроцедуры
Полный независимый пульт и точечная очистка

Модуль общей управляемой формы ПультПрофилейГраниц85

Смешанный управляемый: толстый клиент и сервер

Перем РабочаяФорма;
Перем КвитанцияОчистки;

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

&НаСервереБезКонтекста
Процедура ПроверитьУчебнуюСреду()
Если ИмяПользователя() <> "АвторВариантов85" Тогда
    ВызватьИсключение "Нужен отдельный новый именованный пользователь АвторВариантов85";
КонецЕсли;
Если КлиентскоеПриложение.ТекущийВариантИнтерфейса() <> ВариантИнтерфейсаКлиентскогоПриложения.Такси Тогда
    ВызватьИсключение "Нужен собственный толстый управляемый сеанс Такси";
КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ОткрытьСвойОтчет(Команда)
Если КвитанцияОчистки <> Неопределено Тогда
    ВызватьИсключение "Сначала завершите очистку предыдущей квитанции";
КонецЕсли;
Если РабочаяФорма <> Неопределено Тогда
    Если РабочаяФорма.Открыта() Тогда
        ВызватьИсключение "Собственный отчёт уже открыт";
    КонецЕсли;
    ВызватьИсключение "Не закрывайте отчёт вручную до получения квитанции; начните новый пульт только после собственной ручной проверки записей";
КонецЕсли;
РабочаяФорма = ПолучитьФорму("Отчет.УчебныеГраницыПакетов85.Форма.ПрофилиГраниц85", , ЭтаФорма, Новый УникальныйИдентификатор);
Если РабочаяФорма = Неопределено Тогда
    ВызватьИсключение "Собственная форма отказала в создании";
КонецЕсли;
РабочаяФорма.Открыть();
КонецПроцедуры

&НаКлиенте
Процедура ЗакрытьИУдалитьСозданное(Команда)
Попытка
    Если КвитанцияОчистки = Неопределено Тогда
        Если РабочаяФорма = Неопределено Тогда
            ВызватьИсключение "Нет собственного экземпляра отчёта";
        КонецЕсли;
        Если Не РабочаяФорма.Открыта() Тогда
            ВызватьИсключение "Отчёт закрыли до получения квитанции; автоматическое удаление запрещено";
        КонецЕсли;
        КвитанцияОчистки = РабочаяФорма.ПолучитьКвитанциюОчистки();
    КонецЕсли;
    Если РабочаяФорма.Открыта() Тогда
        РабочаяФорма.Закрыть();
    КонецЕсли;
    Если РабочаяФорма.Открыта() Тогда
        ВызватьИсключение "Собственная форма ещё открыта; удаление запрещено";
    КонецЕсли;
    УдалитьПоСобственнойКвитанции(КвитанцияОчистки);
    РабочаяФорма = Неопределено;
    КвитанцияОчистки = Неопределено;
    Сообщить("Проверено отсутствие только своих pending/созданных записей после точечного Delete и readback. Системные текущие ключи, история и весь профиль не очищались");
Исключение
    Сообщить("Очистка не подтверждена: " + ОписаниеОшибки() + ". Квитанция сохранена для повторной узкой попытки, чужие записи не выбираются");
    Если КвитанцияОчистки <> Неопределено Тогда
        Сообщить(СтрШаблон("Непроверенная очистка своего объекта %1 пользователя %2: А=%3 pending=%4; Б=%5 pending=%6; база=%7 pending=%8", КвитанцияОчистки.Объект, КвитанцияОчистки.Пользователь, КвитанцияОчистки.КлючА, КвитанцияОчистки.ОчиститьА, КвитанцияОчистки.КлючБ, КвитанцияОчистки.ОчиститьБ, КвитанцияОчистки.КлючБазы, КвитанцияОчистки.ОчиститьБазу));
    Иначе
        Сообщить("Квитанция ещё не получена: автоматическое удаление не выполнялось. В собственном отчёте проверьте показанные pending ключи; не объявляйте опыт завершённым");
    КонецЕсли;
КонецПопытки;
КонецПроцедуры

&НаСервереБезКонтекста
Процедура УдалитьПоСобственнойКвитанции(Квитанция)
ПроверитьУчебнуюСреду();
Если ТипЗнч(Квитанция) <> Тип("Структура") Тогда
    ВызватьИсключение "Нужна квитанция реального собственного Save";
КонецЕсли;
Если Квитанция.Объект <> "Отчет.УчебныеГраницыПакетов85" Или Квитанция.Пользователь <> ИмяПользователя() Или Квитанция.Пользователь = "" Или Квитанция.Область = "" Тогда
    ВызватьИсключение "Квитанция не принадлежит собственным отчёту, сеансу и пользователю";
КонецЕсли;
Если Квитанция.Префикс <> "УчебныеПакеты85_" + Квитанция.Область + "_" Или Квитанция.КлючА <> Квитанция.Префикс + "А" Или Квитанция.КлючБ <> Квитанция.Префикс + "Б" Тогда
    ВызватьИсключение "Квитанция содержит ключ вне выделенного namespace";
КонецЕсли;
Если ТипЗнч(Квитанция.СозданА) <> Тип("Булево") Или ТипЗнч(Квитанция.СозданБ) <> Тип("Булево") Или ТипЗнч(Квитанция.СозданБаза) <> Тип("Булево") Тогда
    ВызватьИсключение "Повреждены отметки завершённого Save";
КонецЕсли;
Если ТипЗнч(Квитанция.ОчиститьА) <> Тип("Булево") Или ТипЗнч(Квитанция.ОчиститьБ) <> Тип("Булево") Или ТипЗнч(Квитанция.ОчиститьБазу) <> Тип("Булево") Тогда
    ВызватьИсключение "Повреждены отметки возможной записи собственных pending ключей";
КонецЕсли;
Если (Квитанция.СозданА И Не Квитанция.ОчиститьА) Или (Квитанция.СозданБ И Не Квитанция.ОчиститьБ) Или (Квитанция.СозданБаза И Не Квитанция.ОчиститьБазу) Тогда
    ВызватьИсключение "У завершённого Save потеряна запись собственного ownership для cleanup";
КонецЕсли;
Если Квитанция.КлючБазы <> Квитанция.Префикс + "База" Тогда
    ВызватьИсключение "Повреждён ключ созданного базового варианта";
КонецЕсли;
ОбъектПрофилей = Квитанция.Объект + "/" + Квитанция.КлючБазы;
ХранилищеПрофилей = ПолучитьСтандартноеХранилищеПользовательскихНастроекОтчетов();
Если Квитанция.ОчиститьА Тогда
    УдалитьТолькоСозданнуюЗапись(ХранилищеПрофилей, ОбъектПрофилей, Квитанция.КлючА, Квитанция.Пользователь, Квитанция.Префикс);
КонецЕсли;
Если Квитанция.ОчиститьБ Тогда
    УдалитьТолькоСозданнуюЗапись(ХранилищеПрофилей, ОбъектПрофилей, Квитанция.КлючБ, Квитанция.Пользователь, Квитанция.Префикс);
КонецЕсли;
Если Квитанция.ОчиститьБазу Тогда
    УдалитьТолькоСозданнуюЗапись(ПолучитьСтандартноеХранилищеВариантовОтчетов(), Квитанция.Объект, Квитанция.КлючБазы, Квитанция.Пользователь, Квитанция.Префикс);
КонецЕсли;
КонецПроцедуры

&НаСервереБезКонтекста
Процедура УдалитьТолькоСозданнуюЗапись(Хранилище, Объект, Ключ, Пользователь, Префикс)
Если ТипЗнч(Объект) <> Тип("Строка") Или ТипЗнч(Ключ) <> Тип("Строка") Или ТипЗнч(Пользователь) <> Тип("Строка") Тогда
    ВызватьИсключение "Удалить требует три конкретные строки";
КонецЕсли;
Если Объект = "" Или Ключ = "" Или Пользователь = "" Или Пользователь <> ИмяПользователя() Или Лев(Ключ, СтрДлина(Префикс)) <> Префикс Тогда
    ВызватьИсключение "Широкое удаление или чужой ключ запрещены";
КонецЕсли;
Хранилище.Удалить(Объект, Ключ, Пользователь);
Если Хранилище.Загрузить(Объект, Ключ, , Пользователь) <> Неопределено Тогда
    ВызватьИсключение "После точечного Удалить readback всё ещё нашёл запись";
КонецЕсли;
КонецПроцедуры
Полный запуск собственного стенда

Модуль управляемого приложения новой конфигурации УчебныеВариантыПакетов85; событие ПриНачалеРаботыСистемы

Толстый клиент, управляемое приложение

Процедура ПриНачалеРаботыСистемы()
ОткрытьФорму("ОбщаяФорма.ПультПрофилейГраниц85", , , Новый УникальныйИдентификатор);
КонецПроцедуры

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

  1. Подготовьте новый пустой стенд, нового пользователя, роль с СохранениеДанныхПользователя, свой отчёт/форму, отдельный пульт и соответствующий полный запуск. Здесь всё остаётся текстом, runtime0.

  2. Откройте только собственный экземпляр через пульт. Полный модуль строит query с двумя настоящими schema-параметрами Минимум и Максимум; тип каждого — ОписаниеТипов("Число",КвалификаторыЧисла(1,0,Неотрицательный)).

  3. Проверьте подготовку источника/полей/детальных записей. Для каждого основного значения устанавливаются ID ГраницаПакетов85_Минимум/Максимум и представления Количество: Минимум/Максимум; использование включено. LoadSettings заново получает user-копию на основе этих настроек.

  4. Нажмите СоздатьСвоиПрофили. До Save профиль0..9 обязан иметь ровно два parameter-value элемента, только собственные uniqueID, Number значения, Bool использование=true, typed РежимОтображения=Авто; основные и дополнительные свойства пусты, actual ДополнительныеНастройки имеют0элементов/0свойств. Иной состав — отказ.

  5. Реальный базовый вариант сначала записывается под КлючБазы и проверяется полным typed XML+описанием+границами0..9. Профили пишутся строго под native объектом Отчет.УчебныеГраницыПакетов85/реальныйКлючБазы, не под выдуманным UUID-вариантом.

  6. Профиль Все0..9 сохраняется и целиком сверяется при readback; затем новый LoadSettings создаёт user-слой Узко2..3. В каждом профиле явно задаётся сохранённый режим Авто, затем меняются числовые Значение. Main режим Обычный остаётся прежним; Авто получает его из основных настроек, но это не ручная проверка UI. Readonly контейнеры, user.Параметр, user.Родитель, user.ЗначенияВложенныхПараметров и user.ПредставлениеПользовательскойНастройки не читаются/не переприсваиваются.

  7. До report-setters оба полных user-профиля, их сохранённые представления и неизменность всего сохранённого базового Settings проверяются; после выбора реальные текущие ключи/представления и effective0..9 обязаны совпасть.

  8. В actual ПолеРезультата вручную сверяйте все три детали ПакетА/3/60, ПакетБ/1/20, ПакетВ/6/120. Общего итога схема не задаёт. Флаг событий не делает эту сверку вместо вас.

  9. Нажмите УзкиеГраницы: повторное полное Load-сравнение, настоящий текущий базовый вариант, текущий profile-key/представление; основная база остаётся0..9, actual effective становится2..3. В actual документе вручную должна остаться единственная полная деталь ПакетА/3/60.

  10. Нажмите ВернутьВсе: actual effective0..9 и прежний базовый ключ/представление; вручную снова сверяйте все три детали. Не используйте автоимена клеток или ожидаемый Python-список как доказательство вывода.

  11. В пульте ЗакрытьИУдалитьСозданное получает квитанцию, закрывает только свою форму и требует Открыта=false. Cleanup удаляет учтённые А/Б из report/base namespace, затем учтённую базу из report namespace; каждый readback — Неопределено.

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

  1. Оба parameter ID и оба main-представления реально проверяются; их прежнее supporting-only использование не считалось API покрытием.

  2. Полный user-состав проверяется до Save и после Load: тип, ровно2элемента, оба uniqueID, Number значения, Bool использование=true, собственный enum Авто, отсутствие неожиданных элементов и дополнительных свойств/настроек. Actual main Обычный — источник режима для user Авто по native; поле режима в числовой effective-копии не используется как обещание разрешения Авто. UI вручную; режим включён для полноты payload, не отдельного покрытия.

  3. Для user-копии используются документированные Элементы.Найти(StringID); ПолучитьОбъектПоИдентификатору с типом ИдентификаторКомпоновкиДанных здесь не подменён строкой.

  4. ПредставлениеПользовательскойНастройки и Параметр читаются только у основной настройки, не у user-объекта.

  5. Числа ограничены собственными целыми0..9; явные qualifiers обязательны. Строка "3" или неверный ID не допускаются.

  6. Полное базовое Settings + описание сохраняются неизменными, текущий базовый ключ проверен до и после user-setter; effective границы подтверждены actual компоновщиком.

  7. Числовой/визуальный результат0..9/2..3/0..9 отдельно ручной; actual события показывают только маршрут, не данные.

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

Будущий результат: создан и fully readback-проверен свой базовый вариант и два минимальных user-профиля; report-setters меняют actual effective границы при сохранении базы; реальные детали сверены вручную, затем удалены только три созданные записи. Здесь runtime0 и никаких записей.

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

  1. Только новый именованный пользователь собственной новой базы; всё сохраняющее поведение — будущий ручной BSL, не исполнение здесь.

  2. Это не универсальный comparer чужого графа UserSettings. Подготовка допускает только два своих параметра; неожиданные основные или дополнительные элементы/свойства приводят к отказу, не игнорируются.

  3. Нативный тип UserSettings не обещает XML/XDTO: полный user-профиль сравнивается структурно, XML применяется только к документированному Settings.

  4. ДополнительныеНастройки readonly UserSettings содержат элементы, отмеченные в отборе/условном оформлении; наша схема их не создаёт. Вложенный произвольный граф дополнительных настроек не поддерживается.

  5. Не меняйте пользовательские ID вручную после создания; новый профиль должен оставаться exact составом своего базового варианта.

  6. Если runtime LoadSettings неожиданно добавит элементы или дополнительные свойства, урок fail-closed остановится; нельзя удалить их для искусственного сообщения успех.

  7. Сохранённый базовый вариант, основная настройка компоновщика и effective-результат — разные уровни; user0..9↔2..3 не переписывает сохранённую базу.

  8. Закрытие/смена варианта может писать внутренние системные текущие настройки. Точечное удалениеА/Б/База не удаляет системную историю, весь профиль и не обещает отсутствие внутренних операций.

  9. Ни один Delete не может использовать Неопределено или пустую строку вместо собственного объекта/ключа/пользователя.

  10. Ожидаемые детали выведены из своего константного запроса для будущего ручного протокола; это не подтверждение actual табличного результата статическими тестами.

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

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

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

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

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