Создаём настоящую собственную таблицу продаж, обычное поле цены и вычисляемое описание суммы. Проверяем список500/700 и его снятие; у обоих полей меняем формат редактирования и отдельно использование. Поиск, доступные параметры, принадлежность записи и локальный идентификатор проверяются на действующих объектах, независимая копия остаётся исходной.
Где и как запускать
Полный серверный общий модуль УчебныеЗадачи новой пустой конфигурации УчебноеРедактирование85; в1С не запускался.
Подготовка
Только НОВАЯ отдельная пустая база УчебноеРедактирование85 на точной платформе8.5.1.1343, не копия рабочей. Нет бизнес-объектов, расширений, подписок и фоновых заданий. Здесь база не создаётся и код не запускается.
Вручную создайте общий модуль УчебныеЗадачи: Сервер=Да, Вызов сервера=Да; клиентские флаги, Глобальный и Привилегированный=Нет. Весь основной модуль вставьте целиком, не внутрь другой процедуры.
Своя внешняя обработка УчебноеРедактирование85 → управляемая Форма: команда Выполнить, действие Выполнить и кнопка. Полный отдельный модуль формы ниже предназначен только для этого модуля формы. Перед будущим разрешённым опытом сохраните свою базу, выполните F7 вне опыта и откройте свежий сеанс без расширений.
Сам код создаёт A01/3/500 и B02/5/700, Local-источник, объектный набор Продажи85 и соответствующий внешний ключ. Код85 — Строка; Количество85 — Число(1,0), Цена85 — Число(3,0), сумма — Число(6,2), всё числовое неотрицательное. Шесть разрядов ВСЕГО включают два дробных, предел9999.99. У исходных цен дробная часть0 сохраняется при любом формате.
Обычное поле Цена85 и вычисляемое Сумма85 реально принадлежат собственной схеме. У них читается readonly ПараметрыРедактирования; штатный ФорматРедактирования ищется через ДоступныеПараметры.НайтиПараметр с настоящим ПараметрКомпоновкиДанных. Не создаются произвольные параметры, подмена контейнера или неизвестные записи.
Процедура ВыполнитьПример() Экспорт
ПроверитьСвойПустойСтенд();
Если ПривилегированныйРежим() Тогда
ВызватьИсключение "Привилегированный режим не нужен";
КонецЕсли;
Стенд = СоздатьСвойСтендРедактирования();
Цена = СвоеПолеРедактирования(Стенд, "Цена");
ПроверитьСвоеРедактирование(Стенд, "Нет", "", "ЧДЦ=2", Истина, "ЧДЦ=2", Истина);
Цена.УстановитьДоступныеЗначения(СоздатьСвоиЦеныВыбора(Стенд, "Все"));
ПроверитьСвоеРедактирование(Стенд, "Все", "", "ЧДЦ=2", Истина, "ЧДЦ=2", Истина);
Копия = СоздатьСвойСтендРедактирования();
ЦенаКопии = СвоеПолеРедактирования(Копия, "Цена");
ЦенаКопии.УстановитьДоступныеЗначения(СоздатьСвоиЦеныВыбора(Копия, "Все"));
ПроверитьСвоеРедактирование(Копия, "Все", "", "ЧДЦ=2", Истина, "ЧДЦ=2", Истина);
ПроверитьЧужиеЗаписиРедактирования(Стенд, Копия);
Цена.ВыражениеПредставления = "Код85";
ПроверитьСвоеРедактирование(Стенд, "Все", "Код85", "ЧДЦ=2", Истина, "ЧДЦ=2", Истина);
Цена.УстановитьДоступныеЗначения(СоздатьСвоиЦеныВыбора(Стенд, "ТолькоB02"));
ПроверитьСвоеРедактирование(Стенд, "ТолькоB02", "Код85", "ЧДЦ=2", Истина, "ЧДЦ=2", Истина);
ПроверитьСвоеРедактирование(Копия, "Все", "", "ЧДЦ=2", Истина, "ЧДЦ=2", Истина);
УстановитьСвойФормат(Стенд, "Цена", "ЧДЦ=0");
ПроверитьСвоеРедактирование(Стенд, "ТолькоB02", "Код85", "ЧДЦ=0", Истина, "ЧДЦ=2", Истина);
ПроверитьСвоеРедактирование(Копия, "Все", "", "ЧДЦ=2", Истина, "ЧДЦ=2", Истина);
ЗаписьЦены = СвояЗаписьФормата(СвойРедакторПоля(Стенд, "Цена"));
ЗаписьЦены.Использование = Ложь;
ПроверитьСвоеРедактирование(Стенд, "ТолькоB02", "Код85", "ЧДЦ=0", Ложь, "ЧДЦ=2", Истина);
ПроверитьСвоеРедактирование(Копия, "Все", "", "ЧДЦ=2", Истина, "ЧДЦ=2", Истина);
УстановитьСвойФормат(Стенд, "Цена", "ЧДЦ=0");
ПроверитьСвоеРедактирование(Стенд, "ТолькоB02", "Код85", "ЧДЦ=0", Истина, "ЧДЦ=2", Истина);
УстановитьСвойФормат(Стенд, "Сумма", "ЧДЦ=0");
ПроверитьСвоеРедактирование(Стенд, "ТолькоB02", "Код85", "ЧДЦ=0", Истина, "ЧДЦ=0", Истина);
ПроверитьСвоеРедактирование(Копия, "Все", "", "ЧДЦ=2", Истина, "ЧДЦ=2", Истина);
Цена.УстановитьДоступныеЗначения();
ПроверитьСвоеРедактирование(Стенд, "Нет", "Код85", "ЧДЦ=0", Истина, "ЧДЦ=0", Истина);
ЗаписьСуммы = СвояЗаписьФормата(СвойРедакторПоля(Стенд, "Сумма"));
ЗаписьСуммы.Использование = Ложь;
ПроверитьСвоеРедактирование(Стенд, "Нет", "Код85", "ЧДЦ=0", Истина, "ЧДЦ=0", Ложь);
ПроверитьСвоеРедактирование(Копия, "Все", "", "ЧДЦ=2", Истина, "ЧДЦ=2", Истина);
УстановитьСвойФормат(Стенд, "Цена", "ЧДЦ=2");
УстановитьСвойФормат(Стенд, "Сумма", "ЧДЦ=2");
Цена.ВыражениеПредставления = "";
ПроверитьСвоеРедактирование(Стенд, "Нет", "", "ЧДЦ=2", Истина, "ЧДЦ=2", Истина);
Цена.УстановитьДоступныеЗначения(СоздатьСвоиЦеныВыбора(Стенд, "Все"));
ПроверитьСвоеРедактирование(Стенд, "Все", "", "ЧДЦ=2", Истина, "ЧДЦ=2", Истина);
ПроверитьСвоеРедактирование(Копия, "Все", "", "ЧДЦ=2", Истина, "ЧДЦ=2", Истина);
ПроверитьЧужиеЗаписиРедактирования(Стенд, Копия);
КонецПроцедуры
Процедура ПроверитьСвойПустойСтенд()
Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
КонецЕсли;
Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
КонецЕсли;
Источники = Новый Массив;
Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
Для Каждого Источник Из Источники Цикл
Расширения = РасширенияКонфигурации.Получить(, Источник);
Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
ВызватьИсключение "Native список расширений должен иметь тип Массив";
КонецЕсли;
Если Расширения.Количество() <> 0 Тогда
ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
КонецЕсли;
КонецЦикла;
Если ТранзакцияАктивна() Тогда
ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
КонецЕсли;
КонецПроцедуры
Функция СвояРазрядностьПродаж(Имя)
Если Имя = "Код85" Тогда
Возврат 0;
ИначеЕсли Имя = "Количество85" Тогда
Возврат 1;
ИначеЕсли Имя = "Цена85" Тогда
Возврат 3;
ИначеЕсли Имя = "Сумма85" Тогда
Возврат 6;
КонецЕсли;
ВызватьИсключение "В своей модели продаж только четыре заранее определённых поля";
КонецФункции
Функция СвойТипПродаж(Имя)
Разрядность = СвояРазрядностьПродаж(Имя);
Если Разрядность = 0 Тогда
Возврат Новый ОписаниеТипов("Строка");
КонецЕсли;
ДробнаяЧасть = 0;
Если Разрядность = 6 Тогда
ДробнаяЧасть = 2;
КонецЕсли;
Возврат Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(Разрядность, ДробнаяЧасть, ДопустимыйЗнак.Неотрицательный));
КонецФункции
Процедура ПроверитьСвойТипПродаж(Описание, Имя)
Если ТипЗнч(Описание) <> Тип("ОписаниеТипов") Тогда
ВызватьИсключение "Нужно собственное описание типа продаж";
КонецЕсли;
Разрядность = СвояРазрядностьПродаж(Имя);
ТипПоля = Тип("Число");
Если Разрядность = 0 Тогда
ТипПоля = Тип("Строка");
КонецЕсли;
ПолныеТипы = Описание.Типы();
Если ПолныеТипы.Количество() <> 1 Или ПолныеТипы[0] <> ТипПоля Тогда
ВызватьИсключение "Не совпал полный собственный тип поля продаж";
КонецЕсли;
Если Разрядность = 0 Тогда
Возврат;
КонецЕсли;
ДробнаяЧасть = 0;
Если Разрядность = 6 Тогда
ДробнаяЧасть = 2;
КонецЕсли;
Квалификаторы = Описание.КвалификаторыЧисла;
Если ТипЗнч(Квалификаторы) <> Тип("КвалификаторыЧисла") Или Квалификаторы.Разрядность <> Разрядность
Или Квалификаторы.РазрядностьДробнойЧасти <> ДробнаяЧасть
Или Квалификаторы.ДопустимыйЗнак <> ДопустимыйЗнак.Неотрицательный Тогда
ВызватьИсключение "Не совпали разряды, дробная часть и знак собственного поля продаж";
КонецЕсли;
КонецПроцедуры
Функция СоздатьСвоюОсновуПродаж()
Данные = Новый ТаблицаЗначений;
Имена = СтрРазделить("Код85,Количество85,Цена85", ",");
Для Каждого Имя Из Имена Цикл
Данные.Колонки.Добавить(Имя, СвойТипПродаж(Имя));
КонецЦикла;
СтрокаПродажи = Данные.Добавить();
СтрокаПродажи.Код85 = "A01";
СтрокаПродажи.Количество85 = 3;
СтрокаПродажи.Цена85 = 500;
СтрокаПродажи = Данные.Добавить();
СтрокаПродажи.Код85 = "B02";
СтрокаПродажи.Количество85 = 5;
СтрокаПродажи.Цена85 = 700;
Схема = Новый СхемаКомпоновкиДанных;
Источник = Схема.ИсточникиДанных.Добавить();
Источник.Имя = "СвоиПродажи85";
Источник.ТипИсточникаДанных = "Local";
Набор = Схема.НаборыДанных.Добавить(Тип("НаборДанныхОбъектСхемыКомпоновкиДанных"));
Если ТипЗнч(Набор) <> Тип("НаборДанныхОбъектСхемыКомпоновкиДанных") Тогда
ВызватьИсключение "Нужен собственный объектный набор продаж";
КонецЕсли;
Набор.Имя = "Продажи85";
Набор.ИмяОбъекта = "Продажи85";
Набор.ИсточникДанных = "СвоиПродажи85";
Для Каждого Имя Из Имена Цикл
Поле = Набор.Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
Если ТипЗнч(Поле) <> Тип("ПолеНабораДанныхСхемыКомпоновкиДанных") Тогда
ВызватьИсключение "Нужно собственное простое поле исходных продаж";
КонецЕсли;
Поле.Поле = Имя;
Поле.ПутьКДанным = Имя;
Поле.ТипЗначения = СвойТипПродаж(Имя);
КонецЦикла;
ВнешниеДанные = Новый Структура;
ВнешниеДанные.Вставить("Продажи85", Данные);
Стенд = Новый Структура;
Стенд.Вставить("Схема", Схема);
Стенд.Вставить("ВнешниеДанные", ВнешниеДанные);
Возврат Стенд;
КонецФункции
Процедура ПроверитьСвоюОсновуПродаж(Стенд)
Если ТипЗнч(Стенд) <> Тип("Структура") Или Стенд.Количество() <> 2 Тогда
ВызватьИсключение "Нужна собственная структура схемы и внешних продаж";
КонецЕсли;
Схема = Неопределено;
ВнешниеДанные = Неопределено;
Если Не Стенд.Свойство("Схема", Схема) Или Не Стенд.Свойство("ВнешниеДанные", ВнешниеДанные) Тогда
ВызватьИсключение "Не совпали оба собственных ключа стенда продаж";
КонецЕсли;
Если ТипЗнч(Схема) <> Тип("СхемаКомпоновкиДанных") Или Схема.ИсточникиДанных.Количество() <> 1
Или Схема.НаборыДанных.Количество() <> 1 Тогда
ВызватьИсключение "Нужен единственный собственный источник и объектный набор";
КонецЕсли;
Если ТипЗнч(ВнешниеДанные) <> Тип("Структура") Или ВнешниеДанные.Количество() <> 1 Тогда
ВызватьИсключение "Нужен единственный собственный внешний объект продаж";
КонецЕсли;
Данные = Неопределено;
Если Не ВнешниеДанные.Свойство("Продажи85", Данные) Тогда
ВызватьИсключение "Внешний ключ обязан содержать настоящую собственную таблицу";
КонецЕсли;
Если ТипЗнч(Данные) <> Тип("ТаблицаЗначений") Или Данные.Количество() <> 2 Или Данные.Колонки.Количество() <> 3 Тогда
ВызватьИсключение "Нужны две собственные продажи и три колонки";
КонецЕсли;
Источник = Схема.ИсточникиДанных.Получить(0);
Если ТипЗнч(Источник) <> Тип("ИсточникДанныхСхемыКомпоновкиДанных")
Или Источник.Имя <> "СвоиПродажи85" Или Источник.ТипИсточникаДанных <> "Local" Тогда
ВызватьИсключение "Не совпал собственный логический источник";
КонецЕсли;
Набор = Схема.НаборыДанных.Получить(0);
Если ТипЗнч(Набор) <> Тип("НаборДанныхОбъектСхемыКомпоновкиДанных") Или Набор.Имя <> "Продажи85"
Или Набор.ИмяОбъекта <> "Продажи85" Или Набор.ИсточникДанных <> "СвоиПродажи85"
Или Схема.НаборыДанных.Найти("Продажи85") <> Набор Или Набор.Поля.Количество() <> 3 Тогда
ВызватьИсключение "Не совпал полный собственный набор и его три исходных поля";
КонецЕсли;
Имена = СтрРазделить("Код85,Количество85,Цена85", ",");
Для Индекс = 0 По 2 Цикл
Колонка = Данные.Колонки.Получить(Индекс);
Поле = Набор.Поля.Получить(Индекс);
Если ТипЗнч(Колонка) <> Тип("КолонкаТаблицыЗначений") Или Колонка.Имя <> Имена[Индекс]
Или ТипЗнч(Поле) <> Тип("ПолеНабораДанныхСхемыКомпоновкиДанных")
Или Поле.Поле <> Имена[Индекс] Или Поле.ПутьКДанным <> Имена[Индекс] Тогда
ВызватьИсключение "Не совпали все имена, порядок и пути исходных колонок и полей";
КонецЕсли;
ПроверитьСвойТипПродаж(Колонка.ТипЗначения, Имена[Индекс]);
ПроверитьСвойТипПродаж(Поле.ТипЗначения, Имена[Индекс]);
КонецЦикла;
Коды = СтрРазделить("A01,B02", ",");
Количества = Новый Массив;
Количества.Добавить(3);
Количества.Добавить(5);
Цены = Новый Массив;
Цены.Добавить(500);
Цены.Добавить(700);
Суммы = Новый Массив;
Суммы.Добавить(1500);
Суммы.Добавить(3500);
Для Индекс = 0 По 1 Цикл
СтрокаПродажи = Данные.Получить(Индекс);
Если ТипЗнч(СтрокаПродажи) <> Тип("СтрокаТаблицыЗначений")
Или ТипЗнч(СтрокаПродажи.Код85) <> Тип("Строка") Или СтрокаПродажи.Код85 <> Коды[Индекс]
Или ТипЗнч(СтрокаПродажи.Количество85) <> Тип("Число") Или СтрокаПродажи.Количество85 <> Количества[Индекс]
Или ТипЗнч(СтрокаПродажи.Цена85) <> Тип("Число") Или СтрокаПродажи.Цена85 <> Цены[Индекс]
Или СтрокаПродажи.Количество85 * СтрокаПродажи.Цена85 <> Суммы[Индекс] Тогда
ВызватьИсключение "Не совпали все собственные ячейки и отдельный арифметический эталон BSL";
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Процедура ПроверитьСвойСписокЦен(Список, Эталон)
Если ТипЗнч(Список) <> Тип("СписокЗначений") Или ТипЗнч(Эталон) <> Тип("СписокЗначений") Тогда
ВызватьИсключение "Нужны настоящие собственные списки значений";
КонецЕсли;
Если Список.Количество() <> Эталон.Количество() Тогда
ВызватьИсключение "Не совпало полное количество доступных цен";
КонецЕсли;
Для Индекс = 0 По Эталон.Количество() - 1 Цикл
Элемент = Список.Получить(Индекс);
Ожидаемый = Эталон.Получить(Индекс);
Если ТипЗнч(Элемент) <> Тип("ЭлементСпискаЗначений") Или ТипЗнч(Ожидаемый) <> Тип("ЭлементСпискаЗначений") Тогда
ВызватьИсключение "Нужно читать элементы списка, не непосредственно их значения";
КонецЕсли;
Если ТипЗнч(Элемент.Значение) <> Тип("Число") Или Элемент.Значение <> Ожидаемый.Значение
Или ТипЗнч(Элемент.Представление) <> Тип("Строка") Или Элемент.Представление <> Ожидаемый.Представление
Или ТипЗнч(Элемент.Пометка) <> Тип("Булево") Или Элемент.Пометка <> Ожидаемый.Пометка Тогда
ВызватьИсключение "Не совпали все цены, строковые подписи, пометки и порядок списка";
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция СвоеПолеРедактирования(Стенд, Владелец)
ПроверитьСвоюОсновуПродаж(Стенд);
Расчеты = Стенд.Схема.ВычисляемыеПоля;
Если ТипЗнч(Расчеты) <> Тип("ВычисляемыеПоляСхемыКомпоновкиДанных") Или Расчеты.Количество() <> 1 Тогда
ВызватьИсключение "Нужен единственный собственный расчёт суммы";
КонецЕсли;
Сумма = Расчеты[0];
Если ТипЗнч(Сумма) <> Тип("ВычисляемоеПолеСхемыКомпоновкиДанных")
Или Сумма.ПутьКДанным <> "Сумма85" Или Сумма.Заголовок <> "Сумма продажи"
Или Сумма.Выражение <> "Количество85 * Цена85" Тогда
ВызватьИсключение "Не совпало полное собственное описание суммы";
КонецЕсли;
ПроверитьСвойТипПродаж(Сумма.ТипЗначения, "Сумма85");
Если Владелец = "Сумма" Тогда
Возврат Сумма;
ИначеЕсли Владелец = "Цена" Тогда
Набор = Стенд.Схема.НаборыДанных.Получить(0);
Цена = Набор.Поля.Получить(2);
Если ТипЗнч(Цена) <> Тип("ПолеНабораДанныхСхемыКомпоновкиДанных")
Или Цена.Поле <> "Цена85" Или Цена.ПутьКДанным <> "Цена85" Тогда
ВызватьИсключение "Нужно настоящее собственное поле цены набора";
КонецЕсли;
Возврат Цена;
КонецЕсли;
ВызватьИсключение "В собственном опыте только владельцы Цена или Сумма";
КонецФункции
Функция СвойРедакторПоля(Стенд, Владелец)
Поле = СвоеПолеРедактирования(Стенд, Владелец);
Редактор = Поле.ПараметрыРедактирования;
Если ТипЗнч(Редактор) <> Тип("ПараметрыРедактированияКомпоновкиДанных") Тогда
ВызватьИсключение "Нужен собственный контейнер параметров редактирования поля";
КонецЕсли;
Возврат Редактор;
КонецФункции
Функция СвойДоступныйПараметрФормата(Редактор)
Доступные = Редактор.ДоступныеПараметры;
Если ТипЗнч(Доступные) <> Тип("ДоступныеПараметрыКомпоновкиДанных") Тогда
ВызватьИсключение "Нужен штатный набор доступных параметров своего редактора";
КонецЕсли;
Параметр = Новый ПараметрКомпоновкиДанных("ФорматРедактирования");
Доступный = Доступные.НайтиПараметр(Параметр);
Если ТипЗнч(Доступный) <> Тип("ДоступныйПараметрКомпоновкиДанных") Тогда
ВызватьИсключение "В своём редакторе должен поддерживаться штатный ФорматРедактирования";
КонецЕсли;
Если ТипЗнч(Доступный.Параметр) <> Тип("ПараметрКомпоновкиДанных")
Или ТипЗнч(Доступный.ТипЗначения) <> Тип("ОписаниеТипов")
Или Не Доступный.ТипЗначения.СодержитТип(Тип("Строка")) Тогда
ВызватьИсключение "Параметр формата должен принимать строковое значение";
КонецЕсли;
Возврат Доступный.Параметр;
КонецФункции
Функция СвояЗаписьФормата(Редактор)
Параметр = СвойДоступныйПараметрФормата(Редактор);
Запись = Редактор.НайтиЗначениеПараметра(Параметр);
Если ТипЗнч(Запись) <> Тип("ЗначениеПараметраКомпоновкиДанных") Тогда
ВызватьИсключение "После своей установки нужна настоящая запись значения формата";
КонецЕсли;
Возврат Запись;
КонецФункции
Процедура УстановитьСвойФормат(Стенд, Владелец, Формат)
Если Формат <> "ЧДЦ=2" И Формат <> "ЧДЦ=0" Тогда
ВызватьИсключение "В своём опыте только два документированных числовых формата";
КонецЕсли;
Редактор = СвойРедакторПоля(Стенд, Владелец);
Параметр = СвойДоступныйПараметрФормата(Редактор);
Редактор.УстановитьЗначениеПараметра(Параметр, Формат);
КонецПроцедуры
Процедура ПроверитьСвойФормат(Стенд, Владелец, Формат, Использование)
Редактор = СвойРедакторПоля(Стенд, Владелец);
Запись = СвояЗаписьФормата(Редактор);
Если ТипЗнч(Запись.Значение) <> Тип("Строка") Или Запись.Значение <> Формат
Или ТипЗнч(Запись.Использование) <> Тип("Булево") Или Запись.Использование <> Использование Тогда
ВызватьИсключение "Не совпали собственный полный формат и отдельное состояние использования";
КонецЕсли;
Элементы = Редактор.Элементы;
Если ТипЗнч(Элементы) <> Тип("КоллекцияЗначенийПараметровКомпоновкиДанных") Тогда
ВызватьИсключение "Нужна настоящая коллекция значений своего редактора";
КонецЕсли;
Индекс = Элементы.Индекс(Запись);
Если Индекс < 0 Или Индекс >= Элементы.Количество() Тогда
ВызватьИсключение "Запись формата должна принадлежать собственной коллекции элементов";
КонецЕсли;
Если Элементы.Получить(Индекс) <> Запись Или Элементы[Индекс] <> Запись Или Редактор[Индекс] <> Запись Тогда
ВызватьИсключение "Не совпали поиск и все числовые способы доступа к своей записи";
КонецЕсли;
Идентификатор = Редактор.ПолучитьИдентификаторПоОбъекту(Запись);
Если ТипЗнч(Идентификатор) <> Тип("ИдентификаторКомпоновкиДанных") Тогда
ВызватьИсключение "Для действующей своей записи нужен локальный идентификатор компоновки";
КонецЕсли;
Обратно = Редактор.ПолучитьОбъектПоИдентификатору(Идентификатор);
Если ТипЗнч(Обратно) <> Тип("ЗначениеПараметраКомпоновкиДанных") Или Обратно <> Запись Тогда
ВызватьИсключение "Свой локальный идентификатор должен вернуть ту же текущую запись формата";
КонецЕсли;
КонецПроцедуры
Функция СоздатьСвойСтендРедактирования()
Стенд = СоздатьСвоюОсновуПродаж();
Сумма = Стенд.Схема.ВычисляемыеПоля.Добавить();
Если ТипЗнч(Сумма) <> Тип("ВычисляемоеПолеСхемыКомпоновкиДанных") Тогда
ВызватьИсключение "Добавить обязан вернуть собственное вычисляемое поле";
КонецЕсли;
Сумма.ПутьКДанным = "Сумма85";
Сумма.Выражение = "Количество85 * Цена85";
Сумма.Заголовок = "Сумма продажи";
Сумма.ТипЗначения = СвойТипПродаж("Сумма85");
Цена = СвоеПолеРедактирования(Стенд, "Цена");
Цена.ВыражениеПредставления = "";
Цена.УстановитьДоступныеЗначения();
УстановитьСвойФормат(Стенд, "Цена", "ЧДЦ=2");
УстановитьСвойФормат(Стенд, "Сумма", "ЧДЦ=2");
Возврат Стенд;
КонецФункции
Функция СоздатьСвоиЦеныВыбора(Стенд, Режим)
ПроверитьСвоюОсновуПродаж(Стенд);
Если Режим <> "Все" И Режим <> "ТолькоB02" Тогда
ВызватьИсключение "В своём выборе цен только две продажи или одна B02";
КонецЕсли;
Список = Новый СписокЗначений;
Данные = Стенд.ВнешниеДанные.Продажи85;
Для Индекс = 0 По Данные.Количество() - 1 Цикл
СтрокаПродажи = Данные.Получить(Индекс);
Если Режим = "ТолькоB02" И СтрокаПродажи.Код85 <> "B02" Тогда
Продолжить;
КонецЕсли;
Список.Добавить(СтрокаПродажи.Цена85, СтрокаПродажи.Код85 + " — цена", Ложь);
КонецЦикла;
Возврат Список;
КонецФункции
Процедура ПроверитьСвоеРедактирование(Стенд, Режим, Представление, ФорматЦены, ЦенаИспользуется, ФорматСуммы, СуммаИспользуется)
Цена = СвоеПолеРедактирования(Стенд, "Цена");
Если ТипЗнч(Цена.ВыражениеПредставления) <> Тип("Строка") Или Цена.ВыражениеПредставления <> Представление Тогда
ВызватьИсключение "Не совпало собственное выражение представления исходной цены";
КонецЕсли;
Доступные = Цена.ПолучитьДоступныеЗначения();
Если Режим = "Нет" Тогда
Если Доступные <> Неопределено Тогда
ВызватьИсключение "Снятый список цен должен возвращать Неопределено";
КонецЕсли;
Иначе
Эталон = СоздатьСвоиЦеныВыбора(Стенд, Режим);
ПроверитьСвойСписокЦен(Доступные, Эталон);
КонецЕсли;
ПроверитьСвойФормат(Стенд, "Цена", ФорматЦены, ЦенаИспользуется);
ПроверитьСвойФормат(Стенд, "Сумма", ФорматСуммы, СуммаИспользуется);
КонецПроцедуры
Процедура ПроверитьЧужиеЗаписиРедактирования(Стенд, Копия)
Владельцы = СтрРазделить("Цена,Сумма", ",");
Для Каждого Владелец Из Владельцы Цикл
Редактор = СвойРедакторПоля(Стенд, Владелец);
РедакторКопии = СвойРедакторПоля(Копия, Владелец);
СвояЗапись = СвояЗаписьФормата(Редактор);
ЧужаяЗапись = СвояЗаписьФормата(РедакторКопии);
Если Редактор.ПолучитьИдентификаторПоОбъекту(ЧужаяЗапись) <> Неопределено
Или РедакторКопии.ПолучитьИдентификаторПоОбъекту(СвояЗапись) <> Неопределено Тогда
ВызватьИсключение "Запись другой самостоятельно построенной модели не принадлежит своему редактору";
КонецЕсли;
КонецЦикла;
КонецПроцедурыУчебноеРедактирование85.Форма
Своя внешняя обработка УчебноеРедактирование85 → управляемая Форма → Модуль
Полный отдельный модуль собственной формы с серверным вызовом; здесь не запускался.
&НаКлиенте
Процедура Выполнить(Команда)
ВыполнитьНаСервере();
Сообщить("Свои цены, два параметра формата, использование и локальные идентификаторы проверены; отчёт не выполнялся");
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ВыполнитьНаСервере()
УчебныеЗадачи.ВыполнитьПример();
КонецПроцедурыРазбор по шагам
Список доступных цен строится из настоящих исходных ячеек500/700, с подписями «A01 — цена», «B02 — цена» и пометками Ложь. ТолькоB02 создаёт новый список700. Getter проверяется по всем значениям, типам, подписям, пометкам и порядку. Исходные две строки не фильтруются и не изменяются.
Снятие списка — УстановитьДоступныеЗначения() без аргумента, после чего ожидается Неопределено. Пустой список и явно переданный Неопределено не подставляются по аналогии. Getter-список только читается, общая ссылка или глубокая копия не предполагаются.
ВыражениеПредставления исходной цены меняется на настоящее поле Код85, затем возвращается пустая строка. Это отдельная строка описания, не подпись элемента списка и не формат ввода. Для обычного поля справка описывает переопределение стандартного представления; точное поведение пустой строки не переносится из контракта вычисляемого поля.
ПараметрыРедактирования содержит штатные значения. СвойДоступныйПараметрФормата использует НайтиПараметр, проверяет найденный дескриптор и поддержку Строка его ОписаниеТипов. Перебор с сравнением имён дескрипторов не используется: параметры могут иметь многоязыковые синонимы.
ЧДЦ=2 и ЧДЦ=0 — документированное число десятичных разрядов дробной части. УстановитьЗначениеПараметра принимает найденный ПараметрКомпоновкиДанных и строку; установка включает Использование. Формат не меняет ТипЗначения цены/суммы и не гарантирует принятие дробного ввода. Штатные остальные параметры не очищаются.
НайтиЗначениеПараметра принимает ПараметрКомпоновкиДанных, не строку по аналогии с setter. Возвращённая настоящая запись сверяется с коллекцией Элементы через Индекс, Получить, оба числовых [] и границы. Затем свой GetIDByObject/GetObjectByID должен пройти круг до той же текущей записи.
После каждой установки запись и локальный идентификатор получаются заново. Их сохранение при setter не заявляется. Отдельно выключаем Использование при неизменном ЧДЦ=0, затем повторная установка той же строки должна включить его снова. Старая запись после установки больше не используется.
Двенадцать состояний оригинала проверяют списки/представление и оба формата с флагами: исходное снятие; все цены; представление Код85; толькоB02; формат цены0; отключение цены; повторное включение; формат суммы0; снятие списка; отключение суммы; восстановление обоих форматов/представления; полный исходный список.
Семь сверок независимой модели сохраняют все цены, пустое представление, оба ЧДЦ=2 и использование Истина при изменениях оригинала. В начале и конце чужая настоящая запись копии не должна получать идентификатор у оригинала и наоборот. Чужие идентификаторы для поиска не передаются: глобальная уникальность и невозможность совпадений между владельцами не предполагаются.
Настоящий КА2 КомпоновкаДанныхСервер переносит доступные значения обычного поля после проверки Неопределено. ОбщегоНазначенияУТКлиентСервер ищет запись параметров редактирования через Новый ПараметрКомпоновкиДанных и включает Использование. Эти процедуры и их рабочие поля не вызываются; точный собственный ФорматРедактирования подтверждён установленной справкой, не запуском КА2.
Как проверить результат
Ожидаемый будущий итог: обе исходные продажи неизменны, единственная сумма сохраняет Количество85 * Цена85 и числовые квалификаторы; обычная цена снова имеет500/700 с прежними подписями/Ложь, представление пустое. У обоих редакторов ФорматРедактирования=ЧДЦ=2, Использование=Истина; собственные локальные идентификаторы возвращают действующие записи.
Будущий отрицательный контроль только в отдельно разрешённом стенде: выключить Использование, оставив прежнее ожидание Истина, — проверка должна отказать при той же строке формата и тех же данных. Другие контроли: цена списка701 вместо700, неправильная подпись или запись другого контейнера для локального GetIDByObject. Здесь контроли не запускались.
runtimeVerifiedScenarios=0. Подтверждены установленные типы/сигнатуры/контексты и статическая целостность. Не подтверждены реальные getter/setter/идентификаторы платформы, принятие ввода, маска/формат формы, отображение списка или результат СКД. Арифметический эталон1500/3500 не выдаётся за исполнение движка.
Ожидаемый результат
Полный собственный опыт модели цены и суммы: выбор, представление, формат и использование разделены; действующие записи и их локальная принадлежность проверены без общих данных.
На что обратить внимание
Не заменяйте readonly ПараметрыРедактирования, ДоступныеПараметры, Элементы или тип доступного дескриптора. Не присваивайте Параметр связанной записи: это может вызвать исключение. Редактируется документированный формат и отдельно Использование, остальные штатные значения сохраняются.
Не путайте число дробных знаков формата с КвалификаторыЧисла.РазрядностьДробнойЧасти: цена остаётся собственным целым числом с тремя разрядами, сумма имеет шесть разрядов всего и два дробных. Формат редактирования не делает целое поле дробным и не является правилами финансового округления.
Не держите прежнюю запись/идентификатор через УстановитьЗначениеПараметра и не используйте идентификатор другого редактора как переносимый ключ. Круг ID выполняется внутри своего действующего владельца; чужое членство проверяется по объекту, не по совпадению идентификаторов.
Доступные цены не являются правами доступа, проверкой документа или автоматически установленным отбором. Возвращаемые записи/списки используются только в собственной модели, без предположений о внешнем интерфейсе.
Не создаются настройки выбора, отбор, ресурсы, компоновщик макета или процессор; опыт не является исполнимым отчётом. Нет запуска1С, записи, запросов к рабочим данным, сети или печати. ДоступныеПоляПараметров и ограничения вычисляемого поля остаются отдельными темами, не привязываются ради одной проверки типа.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.