Обновляет объект формы клиентского приложения.
Синтаксис
Прочитать()Полное описание, параметры и ограничения
Расширение формы клиентского приложения для плана видов характеристик.Прочитать (Client application form extension for chart of characteristics types.Read)
Расширение формы клиентского приложения для плана видов характеристик (Client application form extension for chart of characteristics types)
Прочитать (Read)
Доступен, начиная с версии 8.2.
Синтаксис:
Прочитать()
Описание:
Обновляет объект формы клиентского приложения.
Доступность:
Тонкий клиент, веб-клиент, мобильный клиент, сервер, толстый клиент.
Использование в версии:
Доступен, начиная с версии 8.2.
Методическая информация
Практические примеры
Своя форма характеристики: подтвержденная запись3→2, перечитывание675→450 и явный выбор либо отмена
Реальный основной реквизит собственной managed PVH-формы получает сохраненную ссылку. Одна явно согласованная native запись меняет только Множитель3→2; независимый полный запрос подтверждает450. Затем используйте локальную навигацию, guarded choice либо отмену без второй записи.
Где и как запускать
Модуль managed ФормаЭлемента85 собственного PVH УчебныеХарактеристики85, серверные/клиентские директивы в полном MAIN. Новый FileCF/толстый managed Windows/Такси; НЕ ordinary extension. Код авторский, 1С/БД/UI не запускались.
Подготовка
Самостоятельно вручную создайте НОВУЮ пустую файловую ИБ C:\1c-labs\OwnPackage85_6b121b22-8ef2-4454-b15a-1687e22cd660\IB в своей изолированной Windows учебной среде. Ни УТ/КА/УНФ/БП, ни копии чужой базы. Урок только написан: каталоги/VM/ИБ/пользователи здесь не создавались, 1С не запускалась.
Платформа8.5.1.1343, CF Уч85СвояУпаковка, основной режим Управляемое приложение, интерфейс Такси, запуск Толстый клиент, управляемое приложение. CF без расширений всех трех источников, разделителей, RLS, подписок, обработок запуска/обмена/истории, фоновых/регламентных заданий. Единственный учебный сеанс; guards/readback не заменяют блокировки от произвольного параллельного вмешательства.
В Конфигураторе → Конфигурация → свойства своей CF задайте РежимСовместимости=НеИспользовать и обновите только новую учебную ИБ. Режим совместимости отличается от версии исполняемой платформы: версия8.5.1.1343 сама по себе не исключает старый режим. Пример только читает readonly Метаданные.РежимСовместимости и отказывает при ином значении; не меняет настройку программно и не требует ее изменения в рабочих конфигурациях.
Создайте единственную роль Уч85Упаковка с административным правом для native ПолучитьПользователей0 и без ограничений чтение/изменение только своих двух metadata-объектов. Единственный пользователь Уч85Упаковка_6b121b22, назначьте эту роль. Реальный UUID пользователя код получает native ТекущийПользователь, сравнивает со всем native массивом пользователей. Этот UUID вручную запишите в двух полях Пользователь85 при подготовке fixture, не UUID пути/базы/сценария.
Реальный native СтрокаСоединенияИнформационнойБазы должен быть ТОЧНО File="C:\1c-labs\OwnPackage85_6b121b22-8ef2-4454-b15a-1687e22cd660\IB";. При ином формате регистрации остановитесь, разберите его вручную; не меняйте сравнение на поиск подстроки, не разрешайте Srvr/Ref. UUID пути лишь метка новой ИБ, не измеренный UUID самой ИБ.
Создайте Планы видов характеристик → УчебныеХарактеристики85: Иерархический=True (группы и элементы), Код Строка4, Наименование Строка50, тип значений характеристик только Число с квалификаторами Число3,0 неотрицательное. Дополнительные значения характеристик не задавайте. Добавьте реквизиты Метка85/Пользователь85 Строка36 и Множитель85 Число1,0 неотрицательное. Других реквизитов/табличных частей нет; историю данных не включайте. Единственный элемент верхнего уровня, никаких групп: именно в иерархическом объекте Родитель/ЭтоГруппа имеют документированный смысл.
В предопределенных данных PVH создайте единственный элемент Имя=Упаковка85, Код=PACK, Наименование=Свой коэффициент упаковки, не группу. После обновления новой ИБ вручную в Предприятии заполните этот собственный существующий элемент: Метка85=6b121b22-8ef2-4454-b15a-1687e22cd660, Пользователь85=действительный UUID своего пользователя, Множитель85=3, тип значения только Число. Создание/заполнение этого fixture — отдельные ваши ручные действия, не выполняемые примером.
Создайте Справочники → УчебныеУпаковки85: Иерархический=True, вид Иерархия групп и элементов, подчиненный ровно ПланВидовХарактеристик.УчебныеХарактеристики85, владельца использовать Для элементов; Код Строка4, Наименование Строка50, реквизиты Метка85/Пользователь85 Строка36 и Цена85 Число9,2 неотрицательное. Предопределенных данных/табличных частей/истории нет. Единственный элемент верхнего уровня, групп нет. Не переносите ссылки из другой ИБ.
В новой ИБ вручную создайте ровно один обычный элемент справочника: BOX / Своя коробка / Владелец=собственная Упаковка85 / Цена85=225 / те же Метка85 и действительный UUID пользователя. Пометка удаления=False. Должна существовать одна строка PVH и одна строка справочника, никаких скрытых/чужих строк. Права полного чтения обязательны: пустая выборка при RLS не доказывает пустую базу.
Создайте Общий модуль Уч85УпаковкаСтенд: Сервер=True, Вызов сервера=True, Клиент управляемого приложения=False, Глобальный=False, Привилегированный=False, Повторное использование возвращаемых значений=Не использовать. Вставьте полностью COMMON. Он читает полные таблицы и временно блокирует именно собственный сохраненный BSL-экземпляр, но ничего в БД не записывает/удаляет. Никакого отдельного скрытого helper/BSP нет.
Мастером PVH → Формы создайте управляемую ФормаЭлемента85, тип Форма объекта/элемента, основной реквизит Объект:ПланВидовХарактеристикОбъект.УчебныеХарактеристики85. Именно этот реальный metadata-owner дает native расширение, не Новый и не обычная Форма. Назначьте основной формой элемента; не меняйте форму группы/списка/выбора.
После ручной подготовки fixture вставьте полностью FORM в модуль ФормаЭлемента85. События: ПриСозданииНаСервере(Отказ,СтандартнаяОбработка)2, ПередЗаписьюНаСервере(Отказ,ТекущийОбъект,ПараметрыЗаписи)3, ПередЗакрытием(Отказ,ЗавершениеРаботы,ТекстПредупреждения,СтандартнаяОбработка)4. Native callbacks вызывает платформа; вручную их не вызывайте. ПередЗаписьюНаСервере находится ВНЕ транзакции, readback не обещает конкурентную атомарность.
В ФормаЭлемента85 добавьте реквизиты СвояСсылка85:ПланВидовХарактеристикСсылка.УчебныеХарактеристики85, ИсходныйМножитель85:Число1,0, РазрешенаЗапись85/НеизвестныйИсход85/РазрешеноЗакрытие85/СогласиеНаИзменение85:Булево, Статус85:Строка500, Навигация85:Строка1000. Все дополнительные реквизиты СохраняемыеДанные=False. Флажок согласия редактируемый; все остальные поля и Объект.* ТолькоПросмотр=True. Native РежимВыбора/ПараметрыВыбора/ВыборДоступен/ИспользованиеДляГруппИЭлементов НЕ создавайте как свои реквизиты.
Добавьте пять команд ФормаЭлемента85 с одноименными действиями(Команда): СохранитьДве85, Перечитать85, ПодготовитьВыбор85, ПередатьВыбор85, Отменить85. Каждая кнопка ИмяКоманды=одноименная команда. Стандартные Записать/ЗаписатьИЗакрыть/Выбрать не показывайте; неподготовленная штатная запись отказана серверным событием. Учебный протокол не претендует на sandbox произвольного кода. Отменить85 доступна в учебном протоколе после ПодготовитьВыбор85: тогда сохранен полный исходный снимок2/450.
Создайте ОбщаяФорма.Уч85УпаковкаЗапуск, управляемая, без основного прикладного реквизита. Реквизиты Статус85:Строка500 и ВыбраннаяХарактеристика85:ПланВидовХарактеристикСсылка.УчебныеХарактеристики85, ТолькоПросмотр=True, СохраняемыеДанные=False. Команды ОткрытьСвою85 и ИсследоватьБлокировку85 с одноименными действиями(Команда); назначьте native ОбработкаВыбора2 именно событию формы-владельца, не поля ввода. Вставьте полностью LAUNCHER.
В Модуль управляемого приложения вставьте APPLICATION; native ПриНачалеРаботыСистемы0 сначала проверяет подготовленный собственный fixture. Не назначайте этому уроку модуль обычного приложения. Запуск и компиляция выполняются вами вручную после полной проверки схемы/прав/адреса.
Сопоставление native: JSON называет тип Расширение плана видов характеристик, installed справка — Расширение формы клиентского приложения для плана видов характеристик (catalog1649/catalog1890). Все восемь точных страниц реально есть в documentation, но apiKeys=[] из-за короткого экспортного имени. Exact bindings ниже связывают этот alias, не редактируя справку и не кредитуя обычное расширение catalog125.
РежимВыбора default-close передает значение основного реквизита, его тип произвольный: здесь не предполагается, что это PVHRef. Явная команда отключает РежимВыбора и только затем native ОповеститьОВыборе(свояPVHRef,Ложь) передает проверенную ссылку настоящему владельцу. ПараметрыВыбора FixedStructure — собственная прикладная политика двух равенств, не обещание универсальной грамматики фильтров.
Заблокирован0 отвечает, держит ли блокировку ЭТОТ конкретный экземпляр объекта, не вообще заблокирована ли строка кем-либо. Второй экземпляр той же ссылки может вернутьFalse, когда первый держит блокировку. Пример не отключает ограничения обмена и не присваивает readonly ОбменДанными/Предопределенный; читает Загрузка=False/Отправитель=Undefined/Получатели0 как условия собственного обычного процесса.
В BSL нет finally. Cleanup явно присутствует в нормальной ветке и Исключение: освобождается только тот же экземпляр после своего успешного захвата. Если захват/разблокировка/проверка завершается ошибкой, остановитесь: успешный cleanup и rollback не обещаются. Копировать unlock для неизвестного объекта запрещено.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Отказ = Истина;
Паспорт85 = Уч85УпаковкаСтенд.Снимок85();
СвояСсылка85 = Паспорт85.Характеристики[0].Ссылка;
Если Параметры.Ключ <> СвояСсылка85 Или ИмяФормы <> "ПланВидовХарактеристик.УчебныеХарактеристики85.Форма.ФормаЭлемента85" Тогда
ВызватьИсключение "Только реальная форма собственного сохраненного элемента PVH.";
КонецЕсли;
Уч85УпаковкаСтенд.ПроверитьОбъект85(РеквизитФормыВЗначение("Объект"), СвояСсылка85, Паспорт85.Расчет[0].Множитель);
ИсходныйМножитель85 = Паспорт85.Расчет[0].Множитель;
ЭтаФорма.ИспользованиеДляГруппИЭлементов = ИспользованиеГруппИЭлементов.Элементы;
ЭтаФорма.РежимВыбора = Ложь;
ЭтаФорма.ВыборДоступен = Ложь;
ЭтаФорма.ПараметрыВыбора = Новый ФиксированнаяСтруктура(Новый Структура("Метка85,Множитель85", "6b121b22-8ef2-4454-b15a-1687e22cd660", 2));
РазрешенаЗапись85 = Ложь;
НеизвестныйИсход85 = Ложь;
РазрешеноЗакрытие85 = Ложь;
Статус85 = "Сохраненная цена225 × множитель" + Строка(ИсходныйМножитель85) + " = " + Строка(Паспорт85.Расчет[0].Сумма);
Отказ = Ложь;
КонецПроцедуры
&НаСервере
Процедура ПодготовитьСвоюЗапись85()
Если НеизвестныйИсход85 Или ИсходныйМножитель85 <> 3 Или СогласиеНаИзменение85 <> Истина Тогда
ВызватьИсключение "Нужно явное согласие только на одно изменение своего множителя3→2.";
КонецЕсли;
До85 = Уч85УпаковкаСтенд.Снимок85(3);
Если До85.Характеристики[0].Ссылка <> СвояСсылка85 Тогда
ВызватьИсключение "Подменена своя сохраненная ссылка.";
КонецЕсли;
Уч85УпаковкаСтенд.ПроверитьОбъект85(РеквизитФормыВЗначение("Объект"), СвояСсылка85, 3);
Объект.Множитель85 = 2;
РазрешенаЗапись85 = Истина;
КонецПроцедуры
&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
Отказ = Истина;
Если РазрешенаЗапись85 <> Истина Или НеизвестныйИсход85 <> Истина
Или ПараметрыЗаписи.Количество() <> 1 Или ПараметрыЗаписи.Метка85 <> "6b121b22-8ef2-4454-b15a-1687e22cd660" Тогда
ВызватьИсключение "Стандартная/неподготовленная/чужая запись запрещена.";
КонецЕсли;
До85 = Уч85УпаковкаСтенд.Снимок85(3);
Если До85.Характеристики[0].Ссылка <> СвояСсылка85 Тогда
ВызватьИсключение "Изменился полный сохраненный источник перед записью.";
КонецЕсли;
Уч85УпаковкаСтенд.ПроверитьОбъект85(ТекущийОбъект, СвояСсылка85, 2);
РазрешенаЗапись85 = Ложь;
Отказ = Ложь;
КонецПроцедуры
&НаСервере
Функция ПодтвердитьСохраненное85(Множитель85)
Паспорт85 = Уч85УпаковкаСтенд.Снимок85(Множитель85);
Если Паспорт85.Характеристики[0].Ссылка <> СвояСсылка85 Тогда
ВызватьИсключение "Неверная ссылка формы.";
КонецЕсли;
Уч85УпаковкаСтенд.ПроверитьОбъект85(РеквизитФормыВЗначение("Объект"), СвояСсылка85, Множитель85);
Возврат Паспорт85.Расчет[0].Сумма;
КонецФункции
&НаКлиенте
Процедура СохранитьДве85(Команда)
Если Команда.Имя <> "СохранитьДве85" Или НеизвестныйИсход85 Тогда
ВызватьИсключение "Не та команда или неизвестный исход; повторная запись запрещена.";
КонецЕсли;
ПодготовитьСвоюЗапись85();
НеизвестныйИсход85 = Истина;
Попытка
Если ЭтаФорма.Записать(Новый Структура("Метка85", "6b121b22-8ef2-4454-b15a-1687e22cd660")) <> Истина Тогда
ВызватьИсключение "Native Записать вернул Ложь; не повторяйте и не делайте слепое восстановление.";
КонецЕсли;
ЭтаФорма.Прочитать();
Если ПодтвердитьСохраненное85(2) <> 450 Тогда
ВызватьИсключение "Не подтверждены реальные сохраненные2/450.";
КонецЕсли;
ИсходныйМножитель85 = 2;
НеизвестныйИсход85 = Ложь;
Статус85 = "Native Записать=True, Прочитать0, независимый запрос225×2=450; цена и владелец не изменены.";
Исключение
НеизвестныйИсход85 = Истина;
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
&НаКлиенте
Процедура Перечитать85(Команда)
Если Команда.Имя <> "Перечитать85" Или НеизвестныйИсход85 Тогда
ВызватьИсключение "Не перечитываем неизвестный исход вместо расследования.";
КонецЕсли;
ЭтаФорма.Прочитать();
Сумма85 = ПодтвердитьСохраненное85(ИсходныйМножитель85);
Навигация85 = ЭтаФорма.ПолучитьНавигационнуюСсылкуОбъекта();
Если ТипЗнч(Навигация85) <> Тип("Строка") Или Навигация85 = "" Тогда
ВызватьИсключение "Не получена непустая native навигация своего сохраненного объекта.";
КонецЕсли;
Статус85 = "Перечитано, фактическая сумма" + Строка(Сумма85) + "; ссылка показана локально, не открывается и не отправляется.";
КонецПроцедуры
&НаКлиенте
Процедура ПодготовитьВыбор85(Команда)
Если Команда.Имя <> "ПодготовитьВыбор85" Или НеизвестныйИсход85
Или ИсходныйМножитель85 <> 2 Или ПодтвердитьСохраненное85(2) <> 450 Тогда
ВызватьИсключение "Выбираем только свою подтвержденную сохраненную2/450.";
КонецЕсли;
Если ЭтаФорма.ПараметрыВыбора.Метка85 <> "6b121b22-8ef2-4454-b15a-1687e22cd660"
Или ЭтаФорма.ПараметрыВыбора.Множитель85 <> 2 Или ЭтаФорма.ПараметрыВыбора.Количество() <> 2
Или ЭтаФорма.ИспользованиеДляГруппИЭлементов <> ИспользованиеГруппИЭлементов.Элементы Тогда
ВызватьИсключение "Изменена собственная политика выбора.";
КонецЕсли;
Если ВладелецФормы = Неопределено Тогда
ВызватьИсключение "Нужна собственная реальная форма-владелец.";
КонецЕсли;
ВладелецФормы.ПодготовитьПрием85(ЭтаФорма, СвояСсылка85);
ЭтаФорма.РежимВыбора = Истина;
ЭтаФорма.ВыборДоступен = Истина;
ЗакрыватьПриВыборе = Истина;
Если ЭтаФорма.РежимВыбора <> Истина Или ЭтаФорма.ВыборДоступен <> Истина Или ЗакрыватьПриВыборе <> Истина Тогда
ВызватьИсключение "Не подтверждено включение собственного выбора.";
КонецЕсли;
Статус85 = "Выбор подготовлен: выберите явно или отмените без новой записи.";
КонецПроцедуры
&НаКлиенте
Процедура ПередатьВыбор85(Команда)
Если Команда.Имя <> "ПередатьВыбор85" Или ЭтаФорма.РежимВыбора <> Истина
Или ЭтаФорма.ВыборДоступен <> Истина Или НеизвестныйИсход85
Или ПодтвердитьСохраненное85(2) <> 450 Тогда
ВызватьИсключение "Выбор не подготовлен или данные изменились.";
КонецЕсли;
ЭтаФорма.РежимВыбора = Ложь;
ЭтаФорма.ВыборДоступен = Ложь;
РазрешеноЗакрытие85 = Истина;
ОповеститьОВыборе(СвояСсылка85, Ложь);
КонецПроцедуры
&НаКлиенте
Процедура Отменить85(Команда)
Если Команда.Имя <> "Отменить85" Или НеизвестныйИсход85
Или ЭтаФорма.РежимВыбора <> Истина Или ЭтаФорма.ВыборДоступен <> Истина Тогда
ВызватьИсключение "При неизвестном исходе остановитесь; отмена не откат записи.";
КонецЕсли;
Если ПодтвердитьСохраненное85(ИсходныйМножитель85) <> 225 * ИсходныйМножитель85 Тогда
ВызватьИсключение "Исходное сохраненное состояние не подтверждено.";
КонецЕсли;
ВладелецФормы.ПодтвердитьОтмену85(ЭтаФорма, СвояСсылка85, ИсходныйМножитель85);
ЭтаФорма.РежимВыбора = Ложь;
ЭтаФорма.ВыборДоступен = Ложь;
РазрешеноЗакрытие85 = Истина;
Закрыть();
КонецПроцедуры
&НаКлиенте
Процедура ПередЗакрытием(Отказ, ЗавершениеРаботы, ТекстПредупреждения, СтандартнаяОбработка)
Если РазрешеноЗакрытие85 <> Истина Тогда
Отказ = Истина;
СтандартнаяОбработка = Ложь;
ТекстПредупреждения = "Используйте свою явную команду Отменить85; это не rollback.";
КонецЕсли;
КонецПроцедурыCOMMON — полный модуль
Своя новая CF → Общие → Общие модули → Уч85УпаковкаСтенд
Сервер/вызов сервера
Функция ПроверитьСтенд85() Экспорт
Если СтрокаСоединенияИнформационнойБазы() <> "File=""C:\1c-labs\OwnPackage85_6b121b22-8ef2-4454-b15a-1687e22cd660\IB"";" Тогда
ВызватьИсключение "Нужна ровно новая собственная файловая ИБ; рабочие базы запрещены.";
КонецЕсли;
Если Метаданные.РежимСовместимости <> Метаданные.СвойстваОбъектов.РежимСовместимости.НеИспользовать Тогда
ВызватьИсключение "Собственная CF должна работать без режима совместимости; версия платформы не заменяет эту проверку.";
КонецЕсли;
Если Метаданные.Справочники.Количество() <> 1
Или Метаданные.ПланыВидовХарактеристик.Количество() <> 1
Или Метаданные.Документы.Количество() <> 0
Или Метаданные.РегистрыСведений.Количество() <> 0
Или Метаданные.РегистрыНакопления.Количество() <> 0
Или Метаданные.РегистрыБухгалтерии.Количество() <> 0
Или Метаданные.РегистрыРасчета.Количество() <> 0
Или Метаданные.ПланыОбмена.Количество() <> 0 Тогда
ВызватьИсключение "Чужая схема метаданных.";
КонецЕсли;
Если РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.БазаДанных).Количество() <> 0
Или РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.СеансАктивные).Количество() <> 0
Или РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.СеансОтключенные).Количество() <> 0 Тогда
ВызватьИсключение "Стенд должен быть без расширений.";
КонецЕсли;
КаталогМД85 = Метаданные.Справочники.УчебныеУпаковки85;
ВидыМД85 = Метаданные.ПланыВидовХарактеристик.УчебныеХарактеристики85;
Если КаталогМД85.Иерархический <> Истина Или ВидыМД85.Иерархический <> Истина
Или КаталогМД85.Владельцы.Количество() <> 1 Или КаталогМД85.Владельцы.Содержит(ВидыМД85) <> Истина
Или КаталогМД85.ТабличныеЧасти.Количество() <> 0 Или ВидыМД85.ТабличныеЧасти.Количество() <> 0 Тогда
ВызватьИсключение "Нужно точное подчинение, иерархия и отсутствие табличных частей.";
КонецЕсли;
ПроверитьРеквизиты85(КаталогМД85, Новый Структура("Метка85,Пользователь85,Цена85", Тип("Строка"), Тип("Строка"), Тип("Число")));
ПроверитьРеквизиты85(ВидыМД85, Новый Структура("Метка85,Пользователь85,Множитель85", Тип("Строка"), Тип("Строка"), Тип("Число")));
Пользователь85 = ПользователиИнформационнойБазы.ТекущийПользователь();
Если Пользователь85 = Неопределено Тогда
ВызватьИсключение "Не получен действительный аутентифицированный пользователь.";
КонецЕсли;
ВсеПользователи85 = ПользователиИнформационнойБазы.ПолучитьПользователей();
Если ВсеПользователи85.Количество() <> 1
Или Пользователь85.Имя <> "Уч85Упаковка_6b121b22"
Или ВсеПользователи85[0].Имя <> Пользователь85.Имя
Или ВсеПользователи85[0].УникальныйИдентификатор <> Пользователь85.УникальныйИдентификатор Тогда
ВызватьИсключение "Нужен единственный собственный пользователь с административным правом.";
КонецЕсли;
Возврат Строка(Пользователь85.УникальныйИдентификатор);
КонецФункции
Процедура ПроверитьРеквизиты85(ОбъектМД85, Ожидаемые85)
Если ОбъектМД85.Реквизиты.Количество() <> 3 Тогда
ВызватьИсключение "Лишние/отсутствующие реквизиты в собственном объекте.";
КонецЕсли;
Для Каждого Поле85 Из Ожидаемые85 Цикл
Реквизит85 = ОбъектМД85.Реквизиты.Найти(Поле85.Ключ);
Если Реквизит85 = Неопределено Или Реквизит85.Тип.Типы().Количество() <> 1
Или Не Реквизит85.Тип.СодержитТип(Поле85.Значение) Тогда
ВызватьИсключение "Имя/единственный тип своего реквизита не совпадает.";
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция Снимок85(Множитель85 = 0) Экспорт
Пользователь85 = ПроверитьСтенд85();
Запрос85 = Новый Запрос;
Запрос85.Текст =
"ВЫБРАТЬ Ссылка, Код, Наименование, ПометкаУдаления, Предопределенный,
| ИмяПредопределенныхДанных, ЭтоГруппа, Родитель, ТипЗначения,
| Метка85, Пользователь85, Множитель85
|ИЗ ПланВидовХарактеристик.УчебныеХарактеристики85";
Характеристики85 = Запрос85.Выполнить().Выгрузить();
Если Характеристики85.Количество() <> 1 Тогда
ВызватьИсключение "Должен существовать ровно один собственный вид характеристики.";
КонецЕсли;
Х85 = Характеристики85[0];
Если ТипЗнч(Х85.Ссылка) <> Тип("ПланВидовХарактеристикСсылка.УчебныеХарактеристики85")
Или Х85.Ссылка.Пустая() Или Х85.Код <> "PACK" Или Х85.Наименование <> "Свой коэффициент упаковки"
Или Х85.ПометкаУдаления <> Ложь Или Х85.Предопределенный <> Истина
Или Х85.ИмяПредопределенныхДанных <> "Упаковка85" Или Х85.ЭтоГруппа <> Ложь
Или Не Х85.Родитель.Пустая() Или Х85.Метка85 <> "6b121b22-8ef2-4454-b15a-1687e22cd660"
Или Х85.Пользователь85 <> Пользователь85 Или ТипЗнч(Х85.Множитель85) <> Тип("Число")
Или (Х85.Множитель85 <> 3 И Х85.Множитель85 <> 2)
Или (Множитель85 <> 0 И Х85.Множитель85 <> Множитель85)
Или Х85.ТипЗначения.Типы().Количество() <> 1
Или Не Х85.ТипЗначения.СодержитТип(Тип("Число")) Тогда
ВызватьИсключение "Полная сохраненная строка своего PVH отличается от подготовленной.";
КонецЕсли;
Запрос85.Текст =
"ВЫБРАТЬ Ссылка, Код, Наименование, ПометкаУдаления, Предопределенный,
| ИмяПредопределенныхДанных, ЭтоГруппа, Родитель, Владелец, Метка85, Пользователь85, Цена85
|ИЗ Справочник.УчебныеУпаковки85";
Упаковки85 = Запрос85.Выполнить().Выгрузить();
Если Упаковки85.Количество() <> 1 Тогда
ВызватьИсключение "Нужна одна собственная сохраненная упаковка, без чужих строк.";
КонецЕсли;
У85 = Упаковки85[0];
Если ТипЗнч(У85.Ссылка) <> Тип("СправочникСсылка.УчебныеУпаковки85")
Или У85.Ссылка.Пустая() Или У85.Код <> "BOX" Или У85.Наименование <> "Своя коробка"
Или У85.ПометкаУдаления <> Ложь Или У85.Предопределенный <> Ложь
Или У85.ИмяПредопределенныхДанных <> "" Или У85.ЭтоГруппа <> Ложь Или Не У85.Родитель.Пустая()
Или У85.Владелец <> Х85.Ссылка Или У85.Метка85 <> Х85.Метка85
Или У85.Пользователь85 <> Пользователь85 Или У85.Цена85 <> 225 Тогда
ВызватьИсключение "Вся строка упаковки, ее владелец, цена или UUID изменились.";
КонецЕсли;
Запрос85.Текст =
"ВЫБРАТЬ У.Ссылка КАК Упаковка, Х.Ссылка КАК Характеристика,
| У.Цена85 КАК Цена, Х.Множитель85 КАК Множитель,
| У.Цена85 * Х.Множитель85 КАК Сумма
|ИЗ Справочник.УчебныеУпаковки85 КАК У
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ ПланВидовХарактеристик.УчебныеХарактеристики85 КАК Х
| ПО У.Владелец = Х.Ссылка";
Расчет85 = Запрос85.Выполнить().Выгрузить();
Если Расчет85.Количество() <> 1 Или Расчет85[0].Упаковка <> У85.Ссылка
Или Расчет85[0].Характеристика <> Х85.Ссылка Или Расчет85[0].Цена <> 225
Или Расчет85[0].Множитель <> Х85.Множитель85
Или Расчет85[0].Сумма <> 225 * Х85.Множитель85 Тогда
ВызватьИсключение "Независимый полный запрос не подтвердил итог675/450.";
КонецЕсли;
Возврат Новый Структура("Характеристики,Упаковки,Расчет", Характеристики85, Упаковки85, Расчет85);
КонецФункции
Процедура Сравнить85(До85, После85) Экспорт
Для Каждого Ключ85 Из До85 Цикл
ТаблицаПосле85 = После85[Ключ85.Ключ];
ТаблицаДо85 = Ключ85.Значение;
Если ТаблицаДо85.Количество() <> ТаблицаПосле85.Количество()
Или ТаблицаДо85.Колонки.Количество() <> ТаблицаПосле85.Колонки.Количество() Тогда
ВызватьИсключение "Изменился полный объем снимка.";
КонецЕсли;
Для Индекс85 = 0 По ТаблицаДо85.Колонки.Количество() - 1 Цикл
Колонка85 = ТаблицаДо85.Колонки[Индекс85];
Если Колонка85.Имя <> ТаблицаПосле85.Колонки[Индекс85].Имя Тогда
ВызватьИсключение "Изменился порядок/состав полей снимка.";
КонецЕсли;
Для Строка85 = 0 По ТаблицаДо85.Количество() - 1 Цикл
Если Колонка85.Имя = "ТипЗначения" Тогда
Если ТаблицаДо85[Строка85][Колонка85.Имя].Типы().Количество() <> 1
Или ТаблицаПосле85[Строка85][Колонка85.Имя].Типы().Количество() <> 1
Или Не ТаблицаПосле85[Строка85][Колонка85.Имя].СодержитТип(Тип("Число")) Тогда
ВызватьИсключение "Изменился точный тип характеристики.";
КонецЕсли;
ИначеЕсли ТаблицаДо85[Строка85][Колонка85.Имя] <> ТаблицаПосле85[Строка85][Колонка85.Имя] Тогда
ВызватьИсключение "Изменился фактический scalar/ссылка полного снимка.";
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Процедура ПроверитьОбъект85(Характеристика85, Ссылка85, Множитель85) Экспорт
Если ТипЗнч(Характеристика85) <> Тип("ПланВидовХарактеристикОбъект.УчебныеХарактеристики85")
Или Характеристика85.Ссылка <> Ссылка85 Или Характеристика85.Код <> "PACK"
Или Характеристика85.Наименование <> "Свой коэффициент упаковки"
Или Характеристика85.ПометкаУдаления <> Ложь Или Характеристика85.ЭтоГруппа <> Ложь
Или Не Характеристика85.Родитель.Пустая() Или Характеристика85.Предопределенный <> Истина
Или Характеристика85.ИмяПредопределенныхДанных <> "Упаковка85"
Или Характеристика85.Метка85 <> "6b121b22-8ef2-4454-b15a-1687e22cd660"
Или Характеристика85.Пользователь85 <> ПроверитьСтенд85()
Или Характеристика85.Множитель85 <> Множитель85
Или Характеристика85.ТипЗначения.Типы().Количество() <> 1
Или Не Характеристика85.ТипЗначения.СодержитТип(Тип("Число")) Тогда
ВызватьИсключение "Это не точный собственный объект PVH с разрешенным значением.";
КонецЕсли;
Если Характеристика85.ОбменДанными.Загрузка <> Ложь
Или Характеристика85.ОбменДанными.Отправитель <> Неопределено
Или Характеристика85.ОбменДанными.Получатели.Количество() <> 0 Тогда
ВызватьИсключение "Этот процесс не разрешает режим загрузки или обмен.";
КонецЕсли;
КонецПроцедуры
Функция ИсследоватьБлокировку85() Экспорт
До85 = Снимок85();
Ссылка85 = До85.Упаковки[0].Ссылка;
Упаковка85 = Ссылка85.ПолучитьОбъект();
Второй85 = Ссылка85.ПолучитьОбъект();
Если ТипЗнч(Упаковка85) <> Тип("СправочникОбъект.УчебныеУпаковки85")
Или ТипЗнч(Второй85) <> Тип("СправочникОбъект.УчебныеУпаковки85")
Или Упаковка85.Ссылка <> Ссылка85 Или Второй85.Ссылка <> Ссылка85
Или Упаковка85.Код <> "BOX" Или Упаковка85.Наименование <> "Своя коробка"
Или Упаковка85.ПометкаУдаления <> Ложь Или Упаковка85.ЭтоГруппа <> Ложь
Или Не Упаковка85.Родитель.Пустая()
Или Упаковка85.Владелец <> До85.Характеристики[0].Ссылка
Или Упаковка85.Предопределенный <> Ложь Или Упаковка85.ИмяПредопределенныхДанных <> ""
Или Упаковка85.Цена85 <> 225 Или Упаковка85.Метка85 <> До85.Упаковки[0].Метка85
Или Упаковка85.Пользователь85 <> До85.Упаковки[0].Пользователь85 Тогда
ВызватьИсключение "Не получен настоящий сохраненный собственный объект упаковки.";
КонецЕсли;
Если Упаковка85.ОбменДанными.Загрузка <> Ложь
Или Упаковка85.ОбменДанными.Отправитель <> Неопределено
Или Упаковка85.ОбменДанными.Получатели.Количество() <> 0 Тогда
ВызватьИсключение "Блокировка предназначена для обычного своего объекта, не для обмена.";
КонецЕсли;
Характеристика85 = До85.Характеристики[0].Ссылка.ПолучитьОбъект();
ПроверитьОбъект85(Характеристика85, До85.Характеристики[0].Ссылка, До85.Характеристики[0].Множитель85);
Если Упаковка85.Заблокирован() Или Второй85.Заблокирован() Тогда
ВызватьИсключение "Этот экземпляр уже держит блокировку; не освобождаем ее вместо владельца.";
КонецЕсли;
Захвачена85 = Ложь;
Попытка
Сравнить85(До85, Снимок85());
Упаковка85.Заблокировать();
Захвачена85 = Истина;
Если Не Упаковка85.Заблокирован() Или Второй85.Заблокирован() Тогда
ВызватьИсключение "Native predicate должен относиться к конкретному экземпляру, а не ко всем объектам.";
КонецЕсли;
Сравнить85(До85, Снимок85());
Упаковка85.Разблокировать();
Захвачена85 = Ложь;
Если Упаковка85.Заблокирован() Или Второй85.Заблокирован() Тогда
ВызватьИсключение "Не подтверждено освобождение собственной блокировки.";
КонецЕсли;
Исключение
Если Захвачена85 И Упаковка85.Заблокирован() Тогда
Упаковка85.Разблокировать();
Если Упаковка85.Заблокирован() Тогда
ВызватьИсключение "Собственная блокировка не освобождена; остановите учебный сеанс и исследуйте причину.";
КонецЕсли;
КонецЕсли;
ВызватьИсключение;
КонецПопытки;
Сравнить85(До85, Снимок85());
Возврат До85.Расчет[0].Сумма;
КонецФункцииLAUNCHER — полный модуль
Своя новая CF → Общие → Общие формы → Уч85УпаковкаЗапуск → Модуль
Толстый managed клиент, директивы сервера/клиента
Перем СвояФорма85;
Перем СвояСсылка85;
Перем ПриемПодготовлен85;
Перем ПриемВыполнен85;
Перем ЗакрытиеРазрешено85;
Перем СнимокДоВыбора85;
&НаКлиенте
Процедура ОткрытьСвою85(Команда)
Если Команда.Имя <> "ОткрытьСвою85" Или (СвояФорма85 <> Неопределено И ЗакрытиеРазрешено85 <> Истина) Тогда
ВызватьИсключение "Сначала завершите только собственную открытую форму.";
КонецЕсли;
Паспорт85 = Уч85УпаковкаСтенд.Снимок85();
СвояСсылка85 = Паспорт85.Характеристики[0].Ссылка;
СвояФорма85 = ПолучитьФорму("ПланВидовХарактеристик.УчебныеХарактеристики85.Форма.ФормаЭлемента85", Новый Структура("Ключ", СвояСсылка85), ЭтаФорма, Истина);
Если ТипЗнч(СвояФорма85) <> Тип("ФормаКлиентскогоПриложения")
Или СвояФорма85.ИмяФормы <> "ПланВидовХарактеристик.УчебныеХарактеристики85.Форма.ФормаЭлемента85"
Или СвояФорма85.ВладелецФормы <> ЭтаФорма Тогда
ВызватьИсключение "Не получена именно своя managed форма с настоящим владельцем.";
КонецЕсли;
ПриемПодготовлен85 = Ложь;
ПриемВыполнен85 = Ложь;
ЗакрытиеРазрешено85 = Ложь;
СвояФорма85.Открыть();
КонецПроцедуры
&НаКлиенте
Процедура ИсследоватьБлокировку85(Команда)
Если Команда.Имя <> "ИсследоватьБлокировку85" Тогда
ВызватьИсключение "Не та собственная команда.";
КонецЕсли;
Сумма85 = Уч85УпаковкаСтенд.ИсследоватьБлокировку85();
Статус85 = "Свой экземпляр False→True→False; второй экземпляр False. Полные сохраненные строки не изменились, сумма" + Строка(Сумма85);
КонецПроцедуры
&НаКлиенте
Процедура ПодготовитьПрием85(Источник85, Ссылка85) Экспорт
Если Источник85 <> СвояФорма85 Или Ссылка85 <> СвояСсылка85
Или ПриемПодготовлен85 = Истина Или ЗакрытиеРазрешено85 = Истина Тогда
ВызватьИсключение "Чужая или повторная подготовка выбора.";
КонецЕсли;
СнимокДоВыбора85 = Уч85УпаковкаСтенд.Снимок85(2);
Если СнимокДоВыбора85.Характеристики[0].Ссылка <> Ссылка85 Тогда
ВызватьИсключение "Ссылка не соответствует полному фактическому источнику.";
КонецЕсли;
ПриемПодготовлен85 = Истина;
КонецПроцедуры
&НаКлиенте
Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)
Если ПриемПодготовлен85 <> Истина Или ПриемВыполнен85 = Истина
Или ИсточникВыбора <> СвояФорма85
Или ТипЗнч(ВыбранноеЗначение) <> Тип("ПланВидовХарактеристикСсылка.УчебныеХарактеристики85")
Или ВыбранноеЗначение <> СвояСсылка85 Тогда
ВызватьИсключение "Отклонен чужой/default-main-attribute/повторный payload.";
КонецЕсли;
Уч85УпаковкаСтенд.Сравнить85(СнимокДоВыбора85, Уч85УпаковкаСтенд.Снимок85(2));
ПриемВыполнен85 = Истина;
ЗакрытиеРазрешено85 = Истина;
ВыбраннаяХарактеристика85 = ВыбранноеЗначение;
Статус85 = "Native owner ОбработкаВыбора2 принял свою сохраненную PVH-ссылку; новых записей нет.";
КонецПроцедуры
&НаКлиенте
Процедура ПодтвердитьОтмену85(Источник85, Ссылка85, Множитель85) Экспорт
Если Источник85 <> СвояФорма85 Или Ссылка85 <> СвояСсылка85
Или ПриемВыполнен85 = Истина Или ЗакрытиеРазрешено85 = Истина Тогда
ВызватьИсключение "Отмена только своей текущей формы до выбора.";
КонецЕсли;
После85 = Уч85УпаковкаСтенд.Снимок85(Множитель85);
Если После85.Характеристики[0].Ссылка <> СвояСсылка85 Тогда
ВызватьИсключение "Чужое состояние после отмены.";
КонецЕсли;
Если ПриемПодготовлен85 Тогда
Уч85УпаковкаСтенд.Сравнить85(СнимокДоВыбора85, После85);
КонецЕсли;
ЗакрытиеРазрешено85 = Истина;
Статус85 = "Отмена без Notify и без записи, сохраненный множитель" + Строка(Множитель85) + "; ранее сохраненное изменение не отменено.";
КонецПроцедурыAPPLICATION — полный модуль
Своя новая CF → Модуль управляемого приложения
Модуль управляемого приложения, толстый managed клиент
Процедура ПриНачалеРаботыСистемы()
Уч85УпаковкаСтенд.Снимок85();
ОткрытьФорму("ОбщаяФорма.Уч85УпаковкаЗапуск");
КонецПроцедурыРазбор по шагам
Вручную проверьте новую ИБ, единственного пользователя, одну собственную строку каждого объекта и отсутствие иной схемы. Запустите толстый managed клиент, не рабочую базу.
В launcher нажмите ИсследоватьБлокировку85: ожидаются реальные False→True→False именно первого BSL-экземпляра иFalse второго; весь снимок неизменен675. При любом исключении остановитесь, не повторяйте автоматически.
Откройте свою форму через ОткрытьСвою85. До согласия попытка СохранитьДве85 обязана отказать без записи. Перечитать85 показывает собственную навигацию, не открывая URL. Затем отметьте согласие и один раз СохранитьДве85: nativeTrue/read0/полный запрос2/450.
ПодготовитьВыбор85 включает проверенную собственную политику FixedStructure/элементы/ChoiceModeTrue/ChoiceAvailableTrue. В первой форме нажмите Отменить85: Notify не вызывается, ранее сохраненные2/450 остаются, владелец сравнивает полный снимок. Отмена не возвращает3.
Откройте новый собственный экземпляр формы (native unique=True), ПодготовитьВыбор85, ПередатьВыбор85: callback владельца вызывается платформой, принимает только actual child+own PVHRef. После выбора новых записей нет, полный снимок2/450 совпадает. СохранитьДве85 уже недоступна по server guard initial2.
Крестик до явного завершения учебного протокола отказан BeforeClose4 без серверных вызовов. При принудительном завершении приложения/закрытии владельца возможна иная native семантика; это не доказательство cancel или rollback. Зафиксируйте фактический результат вручную, не восстанавливайте3 вслепую.
Как проверить результат
Полный источник: одна PVH-строка с exact native typedref/code/name/predefined/empty-parent/Number type/UUID/user и одна обычная подчиненная catalog-строка с ownowner/price225; три запроса без скрывающих WHERE/ТОП проверяют весь объем.
Independent native joined query возвращает actualrefs/Цена225/Множитель3/Сумма675, после единственной записи2/450. Это не literal подстановка результатов: числа считываются из выполненного запроса, а ожидаемые значения только сравниваются.
До любой будущей записи/блокировки повторяются exactFile/version/currentuser/fullwhitelist guards. Запрос/readback не является конкурентной блокировкой или обещанием общей транзакции.
Предопределенный и ОбменДанными readonly; Владелец и ИмяПредопределенныхДанных здесь только проверяются, не меняются. ПараметрыОбменаДанными не подменяются, режим Загрузка не отключает штатные проверки.
Native callbacks exact2/3/4/2, собственные export2/3 отличаются от native events; неизвестные объекты, чужой owner, alias/RO/wrongarity/context и masked strings/comments проверяются статически. Все 16 PRIMARY реально находятся в своих MAIN, а не кредитуются через supporting-only.
Ожидаемый результат
Полный собственный учебный процесс: сохраненная коробка225×характеристика3=675, одна подтвержденная запись множителя2 дает450; own instance lock снимается явно, выбор передает настоящую own PVH-ссылку, отмена не пишет. Эти исходники статически проверены, но результат выполнения1С пока должен проверить ученик в новой собственной ИБ.
На что обратить внимание
Статический PASS не означает компиляцию/запуск1С. Если схема, тип возврата, native handler или runtime результат отличаются, остановитесь и покажите точную ошибку.
НеизвестныйИсход85 ставится ДО Записать. False/exception/неуспешный readback не разрешают повтор, автоматическое restore или обещанный rollback; состояние расследуется вручную.
ПередЗаписьюНаСервере3 вне транзакции; между guard и write возможны изменения другим кодом. Только одна изолированная учебная сессия, не production алгоритм защиты конкурентных данных.
Default ChoiceMode может передать основной реквизит, а не ссылку. Именно поэтому native Notify здесь явный с типизированной ссылкой и выключенным режимом перед закрытием.
Не печатайте/не отправляйте user UUID или навигационную ссылку в сеть/журнал. Они лишь собственный локальный guard/экран новой ИБ.
History/deprecated API исключены; никакого метода комментария истории, удаления истории, настройки exchange/trust/сертификатов в этом уроке нет.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.