Права, дополнительные индексы и модель хранения собственного справочника

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

Административная проверка отдельного учебного стенда: сначала права Read без ограничения условием, затем два определения дополнительных индексов и описание модели хранения. Полный независимый запрос подтверждает неизменные три лота и сумму 1500 до и после чтения.

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

Собственная новая файловая CF Windows 8.5.1.1343; только толстый обычный клиент и административное чтение. Здесь авторство и статические проверки, без выполнения 1С/БД/UI.

Подготовка

  1. Не используйте рабочую базу или копию конфигурации предприятия. Вручную создайте новую пустую файловую базу строго в C:\1c-labs\OwnAdminDictionary12_41f04b27-380c-42f7-a4d7-5a97ddc3a10b\IB. UUID в имени каталога — метка стенда, а не идентификатор информационной базы. Здесь не выполняются создание базы, запуск 1С, обновление конфигурации или запись данных.

  2. В собственной CF задайте Имя=УчебныйСловарь85, ОсновнойРежимЗапуска=ОбычноеПриложение, РежимСовместимости=НеИспользовать, встроенный язык Русский. Отдельно откройте Сервис → Параметры → Общие → Редактирование конфигурации и выберите режим редактора Оба, чтобы видеть флаги обычного клиента. Оба — настройка редактора, не свойство SupportedRunModes конфигурации.

  3. Создайте одну собственную роль УчебныйАдминистратор85 с Администрированием и полными правами только этой пустой учебной CF, без ограничений доступа к данным. Создайте единственного пользователя УчебныйАдминистратор85 и назначьте ему эту роль. Не меняйте пользователей и права чужих баз. Метод ПолучитьПользователей требует административного права.

  4. Создайте единственный справочник Лоты85: неиерархический, без владельцев, табличных частей и предопределенных элементов. Код=Строка длиной 10, Наименование длиной 50. Реквизиты: Категория85=Строка(20), Сумма85=Число(12,2), Метка85=Строка(40). Все значения одиночного типа; других документов и справочников не добавляйте.

  5. В дереве конфигурации вызовите контекстное меню своего справочника Лоты85 → Дополнительные индексы. Команда также есть на закладке Данные и в палитре свойств объекта. В списке Доступные поля выбирайте только реквизиты основной таблицы этого справочника, не табличные части или виртуальные таблицы.

  6. В редакторе создайте и назовите ПоКатегории85: Индексируемые поля — Категория85; Дополнительные поля — Сумма85. Создайте ПоСумме85: Индексируемые поля — Сумма85, затем Метка85; Дополнительные поля — Категория85. Подтвердите кнопкой OK. Это два определения с тремя ключевыми и двумя дополнительными полями. Не используйте более 16 физических полей в одном индексе.

  7. Обновите конфигурацию только собственного стенда. Native-методика сообщает, что дополнительные индексы создаются или удаляются при реструктуризации. Если СУБД не поддерживает дополнительные неключевые поля, они игнорируются физически. Урок проверяет определения CF, а не число или фактическое наличие физических SQL-индексов.

  8. До вставки модуля запуска создайте три собственных элемента через штатный список Лоты85: L001 / Первый лот / Материалы / 500 / 41f04b27-380c-42f7-a4d7-5a97ddc3a10b:A; L002 / Второй лот / Материалы / 750 / 41f04b27-380c-42f7-a4d7-5a97ddc3a10b:B; L003 / Третий лот / Услуги / 250 / 41f04b27-380c-42f7-a4d7-5a97ddc3a10b:C. Порядок значений: Код, Наименование, Категория85, Сумма85, Метка85. Пометка удаления у всех Ложь. Это явная ручная подготовка собственных записей; код урока ничего не записывает. Других элементов не создавайте.

  9. Создайте общий модуль УчебныйАудит85: КлиентОбычноеПриложение=Да, КлиентУправляемоеПриложение=Нет, Сервер=Нет, ВызовСервера=Нет, ВнешнееСоединение=Нет, Глобальный=Нет, Привилегированный=Нет, ПовторноеИспользованиеВозвращаемыхЗначений=НеИспользовать. Вставьте MAIN целиком. Никаких серверных вызовов и привилегированного обхода прав нет.

  10. Создайте обычную общую форму ПанельАудита85. Реквизит формы Вывод85=Строка неограниченной длины. Добавьте многострочное ПолеВвода Вывод85, Данные=Вывод85, ТолькоПросмотр=Да; кнопку Проверить85 с заголовком Проверить. Вставьте модуль формы целиком. В свойствах формы событие ПриОткрытии свяжите с ПриОткрытии, а у собственной кнопки событие Нажатие с Проверить85(Элемент). Не вызывайте обработчики вручную.

  11. После полной ручной подготовки вставьте supporting-код в модуль обычного приложения, свяжите его ПриНачалеРаботыСистемы с одноименным обработчиком без параметров, обновите свою CF и запустите толстый обычный клиент под своим пользователем. Откроется собственная панель, ничего не читающая из справочника до нажатия Проверить. Это инструкция будущего запуска, а не проверенный здесь runtime.

  12. Нажмите Проверить и сопоставьте реальные имена полей определения с собственной настройкой редактора. API-строки имени таблицы и квалификации полей не подменяются придуманным форматом. Вывод показывает их ровно в том виде, в каком вернула платформа. Повторная кнопка выполняет новый полный readonly-аудит; после ошибки форма остается остановленной, предыдущий вывод не объявляется новым успешным результатом.

Процедура ПроверитьСтенд85() Экспорт
#Если ТолстыйКлиентОбычноеПриложение Тогда
    Если СтрокаСоединенияИнформационнойБазы() <> "File=""C:\1c-labs\OwnAdminDictionary12_41f04b27-380c-42f7-a4d7-5a97ddc3a10b\IB"";" Тогда
        ВызватьИсключение "Разрешена только отдельная собственная файловая учебная база";
    КонецЕсли;
    Если Метаданные.РежимСовместимости <> Метаданные.СвойстваОбъектов.РежимСовместимости.НеИспользовать Или Метаданные.Справочники.Количество() <> 1 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Роли.Количество() <> 1 Тогда
        ВызватьИсключение "Нужна своя новая конфигурация без чужих объектов";
    КонецЕсли;
    Пользователь = ПользователиИнформационнойБазы.ТекущийПользователь();
    Если Пользователь = Неопределено Тогда
        ВызватьИсключение "Нужен собственный явно созданный учебный администратор";
    КонецЕсли;
    Пользователи = ПользователиИнформационнойБазы.ПолучитьПользователей();
    Если Пользователи.Количество() <> 1 Или Пользователь.Имя <> "УчебныйАдминистратор85" Тогда
        ВызватьИсключение "В отдельном стенде должен быть только собственный учебный пользователь";
    КонецЕсли;
    Для Каждого СвойПользователь Из Пользователи Цикл
        Если СвойПользователь.УникальныйИдентификатор <> Пользователь.УникальныйИдентификатор Тогда
            ВызватьИсключение "Пользователь не совпадает с единственным пользователем стенда";
        КонецЕсли;
    КонецЦикла;
    СвойКаталог = Метаданные.Справочники.Лоты85;
    Если СвойКаталог.Имя <> "Лоты85" Или СвойКаталог.Иерархический
        Или СвойКаталог.Владельцы.Количество() <> 0 Или СвойКаталог.ТабличныеЧасти.Количество() <> 0
        Или СвойКаталог.Реквизиты.Количество() <> 3 Тогда
        ВызватьИсключение "Нужен собственный простой справочник с тремя реквизитами";
    КонецЕсли;
#Иначе
    ВызватьИсключение "Урок разрешен только в толстом обычном клиенте своего стенда";
#КонецЕсли
КонецПроцедуры

Функция ПрочитатьЛоты85()
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ Ссылка, Код, Наименование, ПометкаУдаления,
    |Категория85, Сумма85, Метка85 ИЗ Справочник.Лоты85";
    ТаблицаЛотов = Запрос.Выполнить().Выгрузить();
    Если ТаблицаЛотов.Количество() <> 3 Тогда
        ВызватьИсключение "В своем справочнике должны быть ровно три подготовленных лота";
    КонецЕсли;
    Строки = Новый Массив;
    Метки = Новый Массив;
    Ссылки = Новый Массив;
    Итог = 0;
    Для Каждого Лот Из ТаблицаЛотов Цикл
        Если ТипЗнч(Лот.Ссылка) <> Тип("СправочникСсылка.Лоты85")
            Или ТипЗнч(Лот.Код) <> Тип("Строка") Или ТипЗнч(Лот.Наименование) <> Тип("Строка")
            Или ТипЗнч(Лот.ПометкаУдаления) <> Тип("Булево") Или Лот.ПометкаУдаления
            Или ТипЗнч(Лот.Категория85) <> Тип("Строка") Или ТипЗнч(Лот.Сумма85) <> Тип("Число")
            Или ТипЗнч(Лот.Метка85) <> Тип("Строка") Или Лот.Ссылка.Пустая()
            Или Метки.Найти(Лот.Метка85) <> Неопределено Или Ссылки.Найти(Лот.Ссылка) <> Неопределено Тогда
            ВызватьИсключение "Нужны три разные настоящие ссылки и полные типизированные значения";
        КонецЕсли;
        Если Лот.Метка85 = "41f04b27-380c-42f7-a4d7-5a97ddc3a10b:A" Тогда
            Если Лот.Код <> "L001" Или Лот.Наименование <> "Первый лот" Или Лот.Категория85 <> "Материалы" Или Лот.Сумма85 <> 500 Тогда
                ВызватьИсключение "Первый лот не соответствует собственной подготовке";
            КонецЕсли;
        ИначеЕсли Лот.Метка85 = "41f04b27-380c-42f7-a4d7-5a97ddc3a10b:B" Тогда
            Если Лот.Код <> "L002" Или Лот.Наименование <> "Второй лот" Или Лот.Категория85 <> "Материалы" Или Лот.Сумма85 <> 750 Тогда
                ВызватьИсключение "Второй лот не соответствует собственной подготовке";
            КонецЕсли;
        ИначеЕсли Лот.Метка85 = "41f04b27-380c-42f7-a4d7-5a97ddc3a10b:C" Тогда
            Если Лот.Код <> "L003" Или Лот.Наименование <> "Третий лот" Или Лот.Категория85 <> "Услуги" Или Лот.Сумма85 <> 250 Тогда
                ВызватьИсключение "Третий лот не соответствует собственной подготовке";
            КонецЕсли;
        Иначе
            ВызватьИсключение "Обнаружена запись вне трех собственных учебных лотов";
        КонецЕсли;
        Метки.Добавить(Лот.Метка85);
        Ссылки.Добавить(Лот.Ссылка);
        Итог = Итог + Лот.Сумма85;
        Строки.Добавить(Новый ФиксированнаяСтруктура("Ссылка,Код,Наименование,ПометкаУдаления,Категория85,Сумма85,Метка85", Лот.Ссылка, Лот.Код, Лот.Наименование, Лот.ПометкаУдаления, Лот.Категория85, Лот.Сумма85, Лот.Метка85));
    КонецЦикла;
    Если Итог <> 1500 Тогда
        ВызватьИсключение "Ожидался независимый итог 500+750+250=1500";
    КонецЕсли;
    Возврат Новый ФиксированныйМассив(Строки);
КонецФункции

Процедура СравнитьЛоты85(Первые, Вторые)
    Если Первые.Количество() <> 3 Или Вторые.Количество() <> 3 Тогда
        ВызватьИсключение "Изменилось полное количество лотов";
    КонецЕсли;
    Для Каждого ПервыйЛот Из Первые Цикл
        Совпадений = 0;
        Для Каждого ВторойЛот Из Вторые Цикл
            Если ПервыйЛот.Ссылка = ВторойЛот.Ссылка Тогда
                Совпадений = Совпадений + 1;
                Если ПервыйЛот.Код <> ВторойЛот.Код Или ПервыйЛот.Наименование <> ВторойЛот.Наименование
                    Или ПервыйЛот.ПометкаУдаления <> ВторойЛот.ПометкаУдаления Или ПервыйЛот.Категория85 <> ВторойЛот.Категория85
                    Или ПервыйЛот.Сумма85 <> ВторойЛот.Сумма85 Или ПервыйЛот.Метка85 <> ВторойЛот.Метка85 Тогда
                    ВызватьИсключение "Во время административного чтения изменился собственный лот";
                КонецЕсли;
            КонецЕсли;
        КонецЦикла;
        Если Совпадений <> 1 Тогда
            ВызватьИсключение "Состав настоящих собственных ссылок изменился";
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Функция ПрочитатьПоляИндекса85(Поля)
    Если ТипЗнч(Поля) <> Тип("ФиксированныйМассив") Тогда
        ВызватьИсключение "Ожидался собственный readonly массив полей индекса";
    КонецЕсли;
    Имена = Новый Массив;
    Для Каждого ПолеИндекса85 Из Поля Цикл
        Если ТипЗнч(ПолеИндекса85) <> Тип("ПолеИндекса") Тогда
            ВызватьИсключение "Коллекция должна содержать настоящие поля собственного индекса";
        КонецЕсли;
        ИмяПоля = ПолеИндекса85.Имя;
        Если ТипЗнч(ИмяПоля) <> Тип("Строка") Или СокрЛП(ИмяПоля) = ""
            Или Имена.Найти(ИмяПоля) <> Неопределено Тогда
            ВызватьИсключение "Нужно непустое фактическое имя без повторов";
        КонецЕсли;
        Имена.Добавить(ИмяПоля);
    КонецЦикла;
    Возврат Новый ФиксированныйМассив(Имена);
КонецФункции

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

Процедура СравнитьИменаПолей85(Первые, Вторые)
    Если Первые.Количество() <> Вторые.Количество() Тогда
        ВызватьИсключение "Изменилось количество полей определения";
    КонецЕсли;
    ПозицияПервого = 0;
    Для Каждого ПервоеИмя Из Первые Цикл
        ПозицияВторого = 0;
        Для Каждого ВтороеИмя Из Вторые Цикл
            Если ПозицияПервого = ПозицияВторого И ПервоеИмя <> ВтороеИмя Тогда
                ВызватьИсключение "Изменилось имя или порядок полей определения";
            КонецЕсли;
            ПозицияВторого = ПозицияВторого + 1;
        КонецЦикла;
        ПозицияПервого = ПозицияПервого + 1;
    КонецЦикла;
КонецПроцедуры

Процедура СравнитьИндексы85(Первые, Вторые)
    Если Первые.Количество() <> 2 Или Вторые.Количество() <> 2 Тогда
        ВызватьИсключение "Изменилось количество собственных определений";
    КонецЕсли;
    Для Каждого ПервыйИндекс Из Первые Цикл
        Совпадений = 0;
        Для Каждого ВторойИндекс Из Вторые Цикл
            Если ПервыйИндекс.Имя = ВторойИндекс.Имя Тогда
                Совпадений = Совпадений + 1;
                Если ПервыйИндекс.Таблица <> ВторойИндекс.Таблица Тогда
                    ВызватьИсключение "Изменилась таблица собственного определения";
                КонецЕсли;
                СравнитьИменаПолей85(ПервыйИндекс.Ключи, ВторойИндекс.Ключи);
                СравнитьИменаПолей85(ПервыйИндекс.Дополнения, ВторойИндекс.Дополнения);
            КонецЕсли;
        КонецЦикла;
        Если Совпадений <> 1 Тогда
            ВызватьИсключение "Изменился состав определений индексов";
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Процедура ПроверитьКолонки85(Таблица, Имена)
    Если ТипЗнч(Таблица) <> Тип("ТаблицаЗначений") Тогда
        ВызватьИсключение "Структуру хранения должна вернуть настоящая таблица значений";
    КонецЕсли;
    Колонки = СтрРазделить(Имена, ",");
    Если Таблица.Колонки.Количество() <> Колонки.Количество() Тогда
        ВызватьИсключение "Не совпала полная схема административной таблицы";
    КонецЕсли;
    Для Каждого ИмяКолонки Из Колонки Цикл
        Если Таблица.Колонки.Найти(ИмяКолонки) = Неопределено Тогда
            ВызватьИсключение "Нет обязательной колонки структуры хранения: " + ИмяКолонки;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Функция ОписатьСкаляр85(Значение)
    Если Значение = Неопределено Тогда
        Возврат "[Неопределено]";
    КонецЕсли;
    Возврат "[" + Строка(ТипЗнч(Значение)) + "] " + Строка(Значение);
КонецФункции

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

Функция ВыполнитьАудит85() Экспорт
    ПроверитьСтенд85();
    СвойКаталог = Метаданные.Справочники.Лоты85;
    Доступ = ПараметрыДоступа("Read", СвойКаталог, "Категория85,Сумма85,Метка85");
    Если ТипЗнч(Доступ) <> Тип("ПараметрыДоступа") Или ТипЗнч(Доступ.Доступность) <> Тип("Булево")
        Или ТипЗнч(Доступ.ОграничениеУсловием) <> Тип("Булево")
        Или Не Доступ.Доступность Или Доступ.ОграничениеУсловием Тогда
        ВызватьИсключение "До чтения необходимы право Read на свои поля и отсутствие ограничения условием";
    КонецЕсли;
    ЛотыДо = ПрочитатьЛоты85();
    ИндексыДо = ПрочитатьИндексы85(СвойКаталог);
    СвоиОбъекты = Новый Массив;
    СвоиОбъекты.Добавить(СвойКаталог);
    ТаблицыХранения = ПолучитьСтруктуруХраненияБазыДанных(СвоиОбъекты, Ложь);
    ТекстХранения = ОписатьХранение85(ТаблицыХранения);
    ИндексыПосле = ПрочитатьИндексы85(Метаданные.Справочники.Лоты85);
    ЛотыПосле = ПрочитатьЛоты85();
    СравнитьИндексы85(ИндексыДо, ИндексыПосле);
    СравнитьЛоты85(ЛотыДо, ЛотыПосле);
    Текст = "Административное чтение своего стенда. Записи не менялись." + Символы.ПС
        + "Три лота: 500 + 750 + 250 = 1500 до и после проверки." + Символы.ПС
        + "В конфигурации: 2 определения, 3 ключевых и 2 дополнительных поля." + Символы.ПС
        + "Это не количество физических SQL-индексов и не проверка производительности." + Символы.ПС;
    Для Каждого Определение Из ИндексыПосле Цикл
        Текст = Текст + "Определение: " + Определение.Имя + "; фактическая таблица: " + Определение.Таблица + Символы.ПС;
        Для Каждого ИмяКлюча Из Определение.Ключи Цикл
            Текст = Текст + "  Ключ: " + ИмяКлюча + Символы.ПС;
        КонецЦикла;
        Для Каждого ИмяДополнения Из Определение.Дополнения Цикл
            Текст = Текст + "  Дополнительное поле: " + ИмяДополнения + Символы.ПС;
        КонецЦикла;
    КонецЦикла;
    Возврат Текст + Символы.ПС + ТекстХранения;
КонецФункции
Своя панель: только просмотр и настоящая кнопка

Своя CF → Общие → ОбщиеФормы → ПанельАудита85 → Модуль целиком

Только толстый обычный клиент собственного стенда.

Перем Остановка85;

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

Процедура Проверить85(Элемент)
    Попытка
        Если Остановка85 Или Элемент <> ЭлементыФормы.Проверить85 Или ТипЗнч(Элемент) <> Тип("Кнопка") Тогда
            ВызватьИсключение "Нужна собственная кнопка неостановленной панели";
        КонецЕсли;
        Кандидат = УчебныйАудит85.ВыполнитьАудит85();
        Если ТипЗнч(Кандидат) <> Тип("Строка") Или СокрЛП(Кандидат) = "" Тогда
            ВызватьИсключение "Не получен полный административный вывод";
        КонецЕсли;
        Вывод85 = Кандидат;
        Поле = ЭлементыФормы.Вывод85;
        Если Не Поле.ТолькоПросмотр Или Поле.Значение <> Кандидат Тогда
            ВызватьИсключение "Связанный собственный вывод не совпал с результатом проверки";
        КонецЕсли;
    Исключение
        Остановка85 = Истина;
        ВызватьИсключение;
    КонецПопытки;
КонецПроцедуры
Модуль обычного приложения: открыть свою панель

Своя CF → Модуль обычного приложения целиком

Только толстый обычный клиент собственного стенда.

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

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

  1. ПараметрыДоступа возвращает настоящий readonly-объект прав. Пока Доступность не Истина или есть ОграничениеУсловием, запрос к лотам не выполняется.

  2. ДополнительныеИндексы берутся у настоящих метаданных собственного справочника. Перебор дает ДополнительныйИндекс; его массивы содержат настоящие ПолеИндекса. Конструкторов для этих объектов нет.

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

  4. ПолучитьСтруктуруХраненияБазыДанных вызывается только с массивом своего объекта метаданных и Ложь: вывод относится к модели 1С. Полная схема верхней и вложенных таблиц проверяется до обхода; скаляры выводятся вместе с фактическим типом.

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

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

  1. В будущем собственном запуске результат должен показать 2 определения, 3 ключевых и 2 дополнительных поля конфигурации. Собственные суммы 500, 750, 250 дают 1500 до и после проверки.

  2. Увидите полный перечень таблиц, полей и индексов модели для своего справочника. Их количество и имена не задаются заранее и не сравниваются с вымышленной физической SQL-схемой.

  3. В отдельной собственной копии стенда вручную удалите одно определение или измените одну учебную сумму: аудит должен отказать. Не меняйте данные в работающей базе для проверки этого урока.

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

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

Новичок различает разрешение Read, ограничение строк, определение индекса CF и модель хранения. Административное чтение завершается только после полной повторной проверки собственных данных и определений.

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

  1. ПолучитьСтруктуруХраненияБазыДанных предназначен для административного обслуживания и анализа технологического журнала, не для прикладной функциональности. Его результат описывает структуру после реструктуризации; это не исследование фактического SQL-каталога, транзакционная гарантия или тест производительности.

  2. Получить у ДополнительныеИндексы исключен: installed Get6632 объявляет нулевой прототип Получить(), но поясняет получение по индексу. Используется только явно документированный Для Каждого.

  3. ДополнительныйИндекс и ПолеИндекса readonly. ПолеИндекса.Имя не имеет объявленного типа в native-странице: код проверяет фактическую Строку, а не приписывает документации отсутствующий контракт.

  4. Полные snapshots не блокируют параллельные изменения и не доказывают атомарность двух чтений. Работайте в отдельной базе с одним собственным пользователем, без других сессий. Если данные изменились или исход неизвестен, аудит прекращается.

  5. Статические проверки текста и native-контрактов не являются запуском компилятора, 1С, базы или GUI. Здесь не выполнялись права, записи, реструктуризация, SQL-команды или сетевые обращения.

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

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

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

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

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