Расширение формы документа.ПараметрОснование

Свойства · BasisParameter

Содержит ссылку на объект-основание.

Полное описание, параметры и ограничения

Расширение формы документа.ПараметрОснование (Document form extension.BasisParameter)

Расширение формы документа (Document form extension)

ПараметрОснование (BasisParameter)

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

Использование:
Чтение и запись.
Описание:
Содержит ссылку на объект-основание.
Доступность:

Толстый клиент.

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

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

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

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

Учебный счет: запись75, копия45, перепроведение90 и основание20

Полный ordinary File-процесс: сначала новый счет в памяти, потом только отдельное явное согласие пользователя разрешает будущую учебную запись. Проверяем реальные номера, даты, объект и единственный факт регистра, а не имитируем сохранение чтением свойств.

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

Толстый клиент обычного приложения Windows8.5.1.1343, только своя новая File CF. Полный main module ordinary формы документа. Actual runtime/CF/UI/DB/network/filecalls не выполнялись.

Подготовка

  1. Цель: увидеть разницу между новым объектом в памяти, записью документа, проведением и перепроведением. Учебный счет содержит количество, цену и сумму. Его единственная запись факта хранится в своем подчиненном регистре, не в остатках товаров или бухгалтерии.

  2. Вручную создайте отдельную НОВУЮ пустую File-базу C:\1c-labs\OwnDocumentWrite85_1296ea89-366f-4d20-bd9c-5bf37705a3ea\IB. UUID — имя каталога стенда, не UUID информационной базы. Здесь база, CF, пользователи и записи не создаются; все действия ниже предназначены для будущего осознанного ручного опыта.

  3. Windows, платформа8.5.1.1343, толстый обычный клиент. Имя конфигурации УчебнаяЗаписьСчета85; РежимСовместимости=НеИспользовать; поддерживаемые режимы Управляемое приложение и обычное приложение, основной режим Обычное приложение. Ровно один пользователь Счет85Ученик с собственной полной ролью и правом Администрирование. Не устанавливайте расширения БД и сеанса, подписки, регламентные/фоновые задания, обмены или чужие общие модули.

  4. Создайте один документ УчебныйСчет85. ПроведениеРазрешить, ОперативноеПроведениеЗапретить, АвтонумерацияДа, КонтрольУникальностиДа, ТипНомераСтрока, ДлинаНомера9. Табличных частей нет. Не используйте нумератор другого объекта. Точный номер после записи читается фактически, а не предполагается 000000001.

  5. Его пять реквизитов: Маркер85 Строка36; Количество85 Число12,0 неотрицательное; Цена85 Число12,2 неотрицательное; Сумма85 Число15,2 неотрицательное; Основание85 единственный тип ДокументСсылка.УчебныйСчет85. Все стандартные дата/номер/ссылка/проведен/пометка удаления остаются стандартными реквизитами документа.

  6. Создайте один регистр сведений УчебныйФакт85: Непериодический, ПодчинениеРегистратору, измерений и дополнительных реквизитов нет, один ресурс Сумма85 Число15,2 неотрицательное. Единственный регистратор — УчебныйСчет85. В документе отметьте ровно этот регистр на вкладке Движения. ЗаписьДвиженийПриПроведении=ЗаписыватьВыбранные, УдалениеДвижений=УдалятьАвтоматически. Не выбирайте Запретить проведение: документ тогда не является нашим источником движений.

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

  8. OBJECT_MODULE целиком в модуль объекта УчебныйСчет85. ПриКопировании имеет1formal, ОбработкаЗаполнения3, ПередЗаписью3, ОбработкаПроведения2. Платформа вызывает их сама при Copy/Fill/WriteInForm; не вызывайте эти процедуры вручную. Препроцессор допускает только толстый обычный клиент своей File-базы, включая соответствующие части File-приложения; прочие контексты отказывают. ДополнительныеСвойства — непостоянная память объекта, не секрет и не замена правам.

  9. У документа мастер форм→обычная форма документа Счет85, НЕ управляемая. Основной реквизит Документ85 типа ДокументОбъект.УчебныйСчет85, ОсновнойРеквизитДа; ОсновнаяФормаОбъекта=Счет85. FORM_MODULE целиком в модуль формы. Именно эта форма имеет native Расширение формы документа; никакого Новый РасширениеФормыДокумента нет.

  10. Выведите обычные поля номера, даты, количества, цены, суммы, маркировки и основания с привязкой к Документ85; все эти поля ТолькоПросмотрДа, чтобы опыт менялся только предусмотренными командами. Отдельные реквизиты Согласие85 Булево и Состояние85 Строка2000. Состояние readonly. Флажок Согласие85 с явным текстом «Разрешаю этот шаг записи только в моей учебной базе» связывается с Согласие85; начальное значение False задает код.

  11. В форме две обычные кнопки: Провести85 и ПересчитатьКопию85. Нажатие→одноименная процедура(Элемент), по generic ordinary event104. ПередОткрытием→ПередОткрытием(Отказ,СтандартнаяОбработка)2, ПриОткрытии→ПриОткрытии()0, ПередЗаписью→ПередЗаписью(Отказ,РежимЗаписи,РежимПроведения)3, ПослеЗаписи→ПослеЗаписи()0. Это события формы, не одноименные object callbacks.

  12. Удалите стандартные действия Записать/Провести/ОтменитьПроведение/ЗаписатьИЗакрыть и другие команды изменения данных; при попытке обхода native ПередЗаписью формы также отказывает вне нашего разрешенного шага. Не создавайте подписок или обработчиков с дополнительной записью. При закрытии несохраненного кандидата выберите штатное «не сохранять»; проверка ПередЗаписью запрещает автоматическое сохранение без согласия.

  13. Общая обычная форма ПультСчета85: HUB_MODULE в модуль, readonly реквизит Состояние85 Строка2000; три кнопки Источник85/Копия85/Основание85 с Нажатие→одноименный handler(Элемент). Форма ПриОткрытии()0. Объекты и источник не передаются от внешнего пользователя: пульт получает их из полного проверенного запроса только своего стенда.

  14. APPLICATION_MODULE в МодульОбычногоПриложения конфигурации; native ПриНачалеРаботыСистемы()0 открывает собственный ПультСчета85 через ПолучитьОбщуюФорму. После ручного обновления CF запустите этот собственный толстый обычный клиент указанной File-базы; существующее меню рабочей конфигурации не предполагается.

  15. В начале все таблицы должны быть пустыми. Источник85 готовит в памяти новый счет3×25=75. Согласие не включается автоматически. Если вы хотите действительно сделать учебную запись, отдельно поставьте свой флажок и нажмите Провести85. Успех требует True от ЗаписатьВФорме, native ПослеЗаписи и полного чтения документа/факта. Теперь закройте форму без дополнительных изменений.

  16. Копия85 берет настоящий SourceRef из запроса, actual GetObject и native Скопировать(). ПриКопировании готовит новый объект3×15=45; исходный75 не меняется. Внешняя связь ПараметрОбъектКопирования задается этой собственной ссылкой до открытия, проверяется при записи, но сам setter не объявляется механизмом Copy.

  17. В новой форме копии номер должен оставаться пустым: Автонумерация=НеИспользовать откладывает присвоение номера до записи, при metadataАвтонумерацияДа. Отдельно подтвердите проведение45. Для пересчета этой же уже проведенной копии опять включите согласие и нажмите ПересчитатьКопию85: количество6, цена15, сумма90, WriteInForm(Запись) и ПриЗаписиПерепроводитьTrue дают новый сохраненный факт90. Старый факт45 не должен остаться второй строкой. Закройте форму.

  18. Основание85 создает новый actual документ и вызывает native Заполнить(SourceRef). Object ОбработкаЗаполнения готовит1×20=20 и собственный реквизит Основание85. ПараметрОснование формы хранит ту же actual ссылку и проверяется перед открытием/записью; setter не заменяет Fill и не выполняет скрытую запись. Отдельно согласитесь на проведение20, затем закройте форму.

  19. АвтоВремя native readonly: код не присваивает его и не угадывает default. В статусе видны фактический enum режима и сохраненная дата с временем. Новые документы остаются на10.10.2026, но точные секунды и номера до реального запуска не обещаются; повтор проведенной копии должен сохранить ее уже записанную дату и номер.

  20. После каждого успеха читаются ВСЕ строки документа и регистра без ГДЕ, все10полей шапки и4поля факта, объект по каждой ссылке, уникальные маркеры/refs и ровно один active факт на документ. НомерСтроки считывается как реальный native номер, а не предполагается1. В снимок копируются значения всех полей каждой строки: неизменяемые структуры внутри неизменяемых массивов, без сохранения изменяемых строк таблицы. Сравнение проверяет тип и значение каждого поля, число шапок/фактов и соответствие всех строк по маркеру/регистратору в обе стороны. Старые шапки и факты, кроме явно выбранной собственной копии, должны остаться равными по всем этим полям. Разрешение формы хранит полный такой снимок, а не строку, хэш или внутреннюю сериализацию.

  21. Числовой протокол будущего опыта: Source75→факт75/общий75; Copy45→факт45/общий120; RepostCopy90→факт90/общий165; Basis20→факт20/общий185. Source3×25=75 остается неизменным. После каждого шага флажок согласия снимается; повторное создание уже существующего маркера запрещено.

  22. Негативные проверки только на этом своем стенде: без согласия запись отказывает; отмена открытия или закрытие unsaved объекта не должно создавать строки; лишний документ/неактивный факт/дубликат/измененный исходный счет вызывают отказ; неизвестное основание не передавайте. При False/исключении состояние становитсяСТОП. Не обещаем rollback уже совершившейся записи, не удаляем данные и не делаем автоматический retry. Нужен отдельный ручной разбор актуального состояния своего стенда.

Перем Готово85, Остановка85, Источник85, Маршрут85, СнимокДо85, ЗаписьВХоде85, НовыйПеред85, ПровереноПосле85;

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

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

Процедура ПередОткрытием(Отказ, СтандартнаяОбработка)
    Если Готово85 <> Истина Тогда
        Отказ = Истина;
        Возврат;
    КонецЕсли;
    Попытка
        ПроверитьПолитику85();
    Исключение
        Отказ = Истина;
        Остановка85 = Истина;
        ВызватьИсключение;
    КонецПопытки;
КонецПроцедуры

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

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

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

Процедура ВыполнитьЗапись85(Повтор)
    Если Готово85 <> Истина Или Остановка85 = Истина Или ЗаписьВХоде85 = Истина Или Согласие85 <> Истина Тогда
        ВызватьИсключение "Нет готового стенда или отдельного согласия на этот шаг записи";
    КонецЕсли;
    Попытка
        ПроверитьПолитику85();
        Если Не ЗаписьСчета85.РавныСнимки85(ЗаписьСчета85.ПрочитатьВсе85(), СнимокДо85) Тогда
            ВызватьИсключение "Полный снимок перед записью изменился";
        КонецЕсли;
        НовыйПеред85 = Документ85.ЭтоНовый();
        ПровереноПосле85 = Ложь;
        ЗаписьВХоде85 = Истина;
        Документ85.ДополнительныеСвойства.Вставить("РазрешениеФормы85", Новый ФиксированнаяСтруктура("Согласие,Маркер,Маршрут,Снимок,Повтор", Истина, Документ85.Маркер85, Маршрут85, СнимокДо85, Повтор));
        Если ЭтаФорма.ЗаписатьВФорме(?(Повтор, РежимЗаписиДокумента.Запись, РежимЗаписиДокумента.Проведение)) <> Истина Тогда
            ВызватьИсключение "ЗаписатьВФорме вернул Ложь: успех не подтвержден";
        КонецЕсли;
        Если ПровереноПосле85 <> Истина Тогда
            ВызватьИсключение "Нет подтвержденного native ПослеЗаписи и полного повторного чтения";
        КонецЕсли;
        СнимокДо85 = ЗаписьСчета85.ПрочитатьВсе85();
        Состояние85 = "Сохранено: сумма=" + Строка(Документ85.Сумма85) + "; номер=" + Документ85.Номер
            + "; фактическая дата=" + Формат(Документ85.Дата, "ДФ=dd.MM.yyyy HH:mm:ss")
            + "; сумма ВСЕГО собственного регистра=" + Строка(ЗаписьСчета85.ИтогСнимка85(СнимокДо85)) + ". Новое согласие снято.";
        ЗаписьВХоде85 = Ложь;
        Согласие85 = Ложь;
        Документ85.ДополнительныеСвойства.Удалить("РазрешениеФормы85");
    Исключение
        ЗаписьВХоде85 = Ложь;
        Согласие85 = Ложь;
        Остановка85 = Истина;
        Документ85.ДополнительныеСвойства.Удалить("РазрешениеФормы85");
        Состояние85 = "СТОП. Успех и откат не предполагаются: перечитайте свой стенд отдельно, не повторяйте запись этой формой.";
        ВызватьИсключение;
    КонецПопытки;
КонецПроцедуры

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

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

ОбщиеМодули.ЗаписьСчета85.Модуль

Сервер и толстый обычный клиент своей File-базы; только readonly проверки и создание снимков.

Процедура ПроверитьСтенд85() Экспорт
    Если СтрокаСоединенияИнформационнойБазы() <> "File=""C:\1c-labs\OwnDocumentWrite85_1296ea89-366f-4d20-bd9c-5bf37705a3ea\IB"";" Тогда
        ВызватьИсключение "Нужна только своя новая учебная File-база счета";
    КонецЕсли;
    Если Метаданные.РежимСовместимости <> Метаданные.СвойстваОбъектов.РежимСовместимости.НеИспользовать Или Метаданные.Документы.Количество() <> 1 Или Метаданные.РегистрыСведений.Количество() <> 1 Или Метаданные.Справочники.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.Обработки.Количество() <> 0 Или Метаданные.Отчеты.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ОбщиеФормы.Количество() <> 1 Или Метаданные.ОбщиеФормы.Найти("ПультСчета85") = Неопределено Или Метаданные.ОбщиеМодули.Количество() <> 1 Или Метаданные.ОбщиеМодули.Найти("ЗаписьСчета85") = Неопределено Тогда
        ВызватьИсключение "Не совпадает состав отдельной учебной конфигурации";
    КонецЕсли;
    СвойДокумент = Метаданные.Документы.Найти("УчебныйСчет85");
    СвойРегистр = Метаданные.РегистрыСведений.Найти("УчебныйФакт85");
    Если СвойДокумент = Неопределено Или СвойРегистр = Неопределено
        Или СвойДокумент.Проведение <> Метаданные.СвойстваОбъектов.Проведение.Разрешить Или СвойДокумент.ОперативноеПроведение <> Метаданные.СвойстваОбъектов.ОперативноеПроведение.Запретить
        Или СвойДокумент.Автонумерация <> Истина Или СвойДокумент.КонтрольУникальности <> Истина Или СвойДокумент.ТипНомера <> Метаданные.СвойстваОбъектов.ТипНомераДокумента.Строка
        Или СвойДокумент.ДлинаНомера <> 9 Или СвойДокумент.Реквизиты.Количество() <> 5
        Или СвойДокумент.ТабличныеЧасти.Количество() <> 0 Или СвойДокумент.Движения.Количество() <> 1
        Или Не СвойДокумент.Движения.Содержит(СвойРегистр)
        Или СвойДокумент.ЗаписьДвиженийПриПроведении <> Метаданные.СвойстваОбъектов.ЗаписьДвиженийПриПроведении.ЗаписыватьВыбранные
        Или СвойДокумент.УдалениеДвижений <> Метаданные.СвойстваОбъектов.УдалениеДвижений.УдалятьАвтоматически
        Или СвойРегистр.РежимЗаписи <> Метаданные.СвойстваОбъектов.РежимЗаписиРегистра.ПодчинениеРегистратору
        Или СвойРегистр.ПериодичностьРегистраСведений <> Метаданные.СвойстваОбъектов.ПериодичностьРегистраСведений.Непериодический
        Или СвойРегистр.Измерения.Количество() <> 0 Или СвойРегистр.Реквизиты.Количество() <> 0
        Или СвойРегистр.Ресурсы.Количество() <> 1 Или СвойРегистр.Ресурсы.Найти("Сумма85") = Неопределено Тогда
        ВызватьИсключение "Неверна схема счета или его собственного подчиненного регистра";
    КонецЕсли;
    Для Каждого Имя Из СтрРазделить("Маркер85,Количество85,Цена85,Сумма85,Основание85", ",") Цикл
        Если СвойДокумент.Реквизиты.Найти(Имя) = Неопределено Тогда
            ВызватьИсключение "Отсутствует собственный реквизит счета";
        КонецЕсли;
    КонецЦикла;
    Если РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.БазаДанных).Количество() <> 0 Тогда
        ВызватьИсключение "Расширения базы на этом стенде не разрешены";
    КонецЕсли;
    Пользователь = ПользователиИнформационнойБазы.ТекущийПользователь();
    Если ТипЗнч(Пользователь) <> Тип("ПользовательИнформационнойБазы") Тогда
        ВызватьИсключение "Нет описания аутентифицированного собственного пользователя";
    КонецЕсли;
    Пользователи = ПользователиИнформационнойБазы.ПолучитьПользователей();
    Если Пользователь.Имя <> "Счет85Ученик" Или Пользователи.Количество() <> 1
        Или Пользователи[0].УникальныйИдентификатор <> Пользователь.УникальныйИдентификатор Тогда
        ВызватьИсключение "Нужен единственный собственный пользователь Счет85Ученик";
    КонецЕсли;
КонецПроцедуры

Функция Маркер85(Маршрут) Экспорт
    Если Маршрут = "Источник" Тогда
        Возврат "457ec6c5-38d6-4e92-9fdd-3524d3297177";
    ИначеЕсли Маршрут = "Копия" Тогда
        Возврат "5643450f-4d65-442d-a341-aa450a98b2d7";
    ИначеЕсли Маршрут = "Основание" Тогда
        Возврат "a0313f50-8a6b-4c4d-8646-6d344781ac69";
    КонецЕсли;
    ВызватьИсключение "Неизвестный учебный маршрут";
КонецФункции

Функция ОжидаемаяСумма85(Маркер, Количество, Цена) Экспорт
    Если ТипЗнч(Маркер) <> Тип("Строка") Или ТипЗнч(Количество) <> Тип("Число") Или ТипЗнч(Цена) <> Тип("Число") Тогда
        ВызватьИсключение "Нужны собственный маркер и числовые количество/цена";
    КонецЕсли;
    Если Маркер = Маркер85("Источник") И Количество = 3 И Цена = 25 Тогда
        Возврат 75;
    ИначеЕсли Маркер = Маркер85("Копия") И (Количество = 3 Или Количество = 6) И Цена = 15 Тогда
        Возврат Количество * Цена;
    ИначеЕсли Маркер = Маркер85("Основание") И Количество = 1 И Цена = 20 Тогда
        Возврат 20;
    КонецЕсли;
    ВызватьИсключение "Неизвестные строки или числа не записываются";
КонецФункции

Функция СнимокСтроки85(Строка) Экспорт
    Возврат Новый ФиксированнаяСтруктура("Ссылка,Номер,Дата,Проведен,ПометкаУдаления,Маркер85,Количество85,Цена85,Сумма85,Основание85",
        Строка.Ссылка, Строка.Номер, Строка.Дата, Строка.Проведен, Строка.ПометкаУдаления, Строка.Маркер85,
        Строка.Количество85, Строка.Цена85, Строка.Сумма85, Строка.Основание85);
КонецФункции

Функция СнимокФакта85(Факт)
    Возврат Новый ФиксированнаяСтруктура("Регистратор,НомерСтроки,Активность,Сумма85", Факт.Регистратор, Факт.НомерСтроки, Факт.Активность, Факт.Сумма85);
КонецФункции

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

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

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

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

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

Функция РавныСнимки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 КАК С УПОРЯДОЧИТЬ ПО С.Маркер85";
    Шапки = Запрос.Выполнить().Выгрузить();
    Запрос.Текст = "ВЫБРАТЬ Ф.Регистратор, Ф.НомерСтроки, Ф.Активность, Ф.Сумма85
    |ИЗ РегистрСведений.УчебныйФакт85 КАК Ф УПОРЯДОЧИТЬ ПО Ф.Регистратор";
    Факты = Запрос.Выполнить().Выгрузить();
    Если Шапки.Колонки.Количество() <> 10 Или Факты.Колонки.Количество() <> 4
        Или Шапки.Количество() > 3 Или Факты.Количество() <> Шапки.Количество() Тогда
        ВызватьИсключение "Читается весь стенд без ГДЕ: лишние или непроведенные строки запрещены";
    КонецЕсли;
    Уникальные = Новый Соответствие;
    Источник = Шапки.Найти(Маркер85("Источник"), "Маркер85");
    Для Каждого Шапка Из Шапки Цикл
        Если ТипЗнч(Шапка.Ссылка) <> Тип("ДокументСсылка.УчебныйСчет85") Или Шапка.Ссылка.Пустая()
            Или ТипЗнч(Шапка.Номер) <> Тип("Строка") Или Шапка.Номер = "" Или СтрДлина(Шапка.Номер) > 9
            Или ТипЗнч(Шапка.Дата) <> Тип("Дата") Или НачалоДня(Шапка.Дата) <> Дата(2026, 10, 10)
            Или ТипЗнч(Шапка.Проведен) <> Тип("Булево") Или Шапка.Проведен <> Истина
            Или ТипЗнч(Шапка.ПометкаУдаления) <> Тип("Булево") Или Шапка.ПометкаУдаления <> Ложь
            Или ТипЗнч(Шапка.Основание85) <> Тип("ДокументСсылка.УчебныйСчет85")
            Или ТипЗнч(Шапка.Сумма85) <> Тип("Число")
            Или Шапка.Сумма85 <> ОжидаемаяСумма85(Шапка.Маркер85, Шапка.Количество85, Шапка.Цена85)
            Или Уникальные.Получить(Шапка.Маркер85) <> Неопределено Тогда
            ВызватьИсключение "Полный снимок содержит чужую, измененную или повторную шапку";
        КонецЕсли;
        Уникальные.Вставить(Шапка.Маркер85, Истина);
        Если Шапка.Маркер85 = Маркер85("Источник") Тогда
            Если Шапка.Основание85 <> Документы.УчебныйСчет85.ПустаяСсылка() Тогда
                ВызватьИсключение "Исходный счет не должен иметь основания";
            КонецЕсли;
        ИначеЕсли Источник = Неопределено Или Шапка.Основание85 <> Источник.Ссылка Или Шапка.Ссылка = Источник.Ссылка Тогда
            ВызватьИсключение "Копия или основание не относятся к собственному исходному счету";
        КонецЕсли;
        СтрокиФакта = Факты.НайтиСтроки(Новый Структура("Регистратор", Шапка.Ссылка));
        Если СтрокиФакта.Количество() <> 1 Тогда
            ВызватьИсключение "У каждого собственного счета должна быть одна запись факта";
        КонецЕсли;
        Факт = СтрокиФакта[0];
        Если ТипЗнч(Факт.Регистратор) <> Тип("ДокументСсылка.УчебныйСчет85") Или Факт.Регистратор <> Шапка.Ссылка
            Или ТипЗнч(Факт.НомерСтроки) <> Тип("Число") Или ТипЗнч(Факт.Активность) <> Тип("Булево")
            Или Факт.Активность <> Истина Или ТипЗнч(Факт.Сумма85) <> Тип("Число") Или Факт.Сумма85 <> Шапка.Сумма85 Тогда
            ВызватьИсключение "Не совпадают регистратор, активность или сохраненная сумма факта";
        КонецЕсли;
        Объект = Шапка.Ссылка.ПолучитьОбъект();
        Если ТипЗнч(Объект) <> Тип("ДокументОбъект.УчебныйСчет85") Или Объект.ЭтоНовый()
            Или Не РавныШапки85(СнимокСтроки85(Объект), СнимокСтроки85(Шапка)) Тогда
            ВызватьИсключение "Actual GetObject не совпадает с полной шапкой запроса";
        КонецЕсли;
    КонецЦикла;
    ШапкиСнимка = Новый Массив;
    Для Каждого Шапка Из Шапки Цикл
        ШапкиСнимка.Добавить(СнимокСтроки85(Шапка));
    КонецЦикла;
    ФактыСнимка = Новый Массив;
    Для Каждого Факт Из Факты Цикл
        ФактыСнимка.Добавить(СнимокФакта85(Факт));
    КонецЦикла;
    Снимок = Новый ФиксированнаяСтруктура("Шапки,Факты", Новый ФиксированныйМассив(ШапкиСнимка), Новый ФиксированныйМассив(ФактыСнимка));
    ПроверитьСнимок85(Снимок);
    Возврат Снимок;
КонецФункции

Процедура ПроверитьКандидат85(Объект, Маршрут, Источник) Экспорт
    ПроверитьСтенд85();
    Если ТипЗнч(Объект) <> Тип("ДокументОбъект.УчебныйСчет85")
        Или Объект.Маркер85 <> Маркер85(Маршрут) Или ТипЗнч(Объект.Дата) <> Тип("Дата")
        Или НачалоДня(Объект.Дата) <> Дата(2026, 10, 10) Или Объект.ПометкаУдаления <> Ложь
        Или ТипЗнч(Объект.Сумма85) <> Тип("Число")
        Или Объект.Сумма85 <> ОжидаемаяСумма85(Объект.Маркер85, Объект.Количество85, Объект.Цена85)
        Или ТипЗнч(Источник) <> Тип("ДокументСсылка.УчебныйСчет85") Или Объект.Основание85 <> Источник Тогда
        ВызватьИсключение "Нельзя продолжать с посторонним кандидатом счета";
    КонецЕсли;
    Если Маршрут = "Источник" Тогда
        Если Источник <> Документы.УчебныйСчет85.ПустаяСсылка() Тогда
            ВызватьИсключение "Подготовка источника не допускает чужое основание";
        КонецЕсли;
    Иначе
        ИсточникОбъект = Источник.ПолучитьОбъект();
        Если ТипЗнч(ИсточникОбъект) <> Тип("ДокументОбъект.УчебныйСчет85") Или ИсточникОбъект.ЭтоНовый()
            Или ИсточникОбъект.Маркер85 <> Маркер85("Источник") Или ИсточникОбъект.Сумма85 <> 75
            Или ИсточникОбъект.Количество85 <> 3 Или ИсточникОбъект.Цена85 <> 25
            Или ИсточникОбъект.Проведен <> Истина Или ИсточникОбъект.ПометкаУдаления <> Ложь Тогда
            ВызватьИсключение "Основание должно быть реальным собственным сохраненным исходным счетом75";
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

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

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

Документы.УчебныйСчет85.Формы.Счет85.Модуль

Толстый ordinary клиент; main requisite Документ85 реальный ДокументОбъект.УчебныйСчет85.

Перем Готово85, Остановка85, Источник85, Маршрут85, СнимокДо85, ЗаписьВХоде85, НовыйПеред85, ПровереноПосле85;

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

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

Процедура ПередОткрытием(Отказ, СтандартнаяОбработка)
    Если Готово85 <> Истина Тогда
        Отказ = Истина;
        Возврат;
    КонецЕсли;
    Попытка
        ПроверитьПолитику85();
    Исключение
        Отказ = Истина;
        Остановка85 = Истина;
        ВызватьИсключение;
    КонецПопытки;
КонецПроцедуры

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

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

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

Процедура ВыполнитьЗапись85(Повтор)
    Если Готово85 <> Истина Или Остановка85 = Истина Или ЗаписьВХоде85 = Истина Или Согласие85 <> Истина Тогда
        ВызватьИсключение "Нет готового стенда или отдельного согласия на этот шаг записи";
    КонецЕсли;
    Попытка
        ПроверитьПолитику85();
        Если Не ЗаписьСчета85.РавныСнимки85(ЗаписьСчета85.ПрочитатьВсе85(), СнимокДо85) Тогда
            ВызватьИсключение "Полный снимок перед записью изменился";
        КонецЕсли;
        НовыйПеред85 = Документ85.ЭтоНовый();
        ПровереноПосле85 = Ложь;
        ЗаписьВХоде85 = Истина;
        Документ85.ДополнительныеСвойства.Вставить("РазрешениеФормы85", Новый ФиксированнаяСтруктура("Согласие,Маркер,Маршрут,Снимок,Повтор", Истина, Документ85.Маркер85, Маршрут85, СнимокДо85, Повтор));
        Если ЭтаФорма.ЗаписатьВФорме(?(Повтор, РежимЗаписиДокумента.Запись, РежимЗаписиДокумента.Проведение)) <> Истина Тогда
            ВызватьИсключение "ЗаписатьВФорме вернул Ложь: успех не подтвержден";
        КонецЕсли;
        Если ПровереноПосле85 <> Истина Тогда
            ВызватьИсключение "Нет подтвержденного native ПослеЗаписи и полного повторного чтения";
        КонецЕсли;
        СнимокДо85 = ЗаписьСчета85.ПрочитатьВсе85();
        Состояние85 = "Сохранено: сумма=" + Строка(Документ85.Сумма85) + "; номер=" + Документ85.Номер
            + "; фактическая дата=" + Формат(Документ85.Дата, "ДФ=dd.MM.yyyy HH:mm:ss")
            + "; сумма ВСЕГО собственного регистра=" + Строка(ЗаписьСчета85.ИтогСнимка85(СнимокДо85)) + ". Новое согласие снято.";
        ЗаписьВХоде85 = Ложь;
        Согласие85 = Ложь;
        Документ85.ДополнительныеСвойства.Удалить("РазрешениеФормы85");
    Исключение
        ЗаписьВХоде85 = Ложь;
        Согласие85 = Ложь;
        Остановка85 = Истина;
        Документ85.ДополнительныеСвойства.Удалить("РазрешениеФормы85");
        Состояние85 = "СТОП. Успех и откат не предполагаются: перечитайте свой стенд отдельно, не повторяйте запись этой формой.";
        ВызватьИсключение;
    КонецПопытки;
КонецПроцедуры

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

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

Документы.УчебныйСчет85.МодульОбъекта

Native object callbacks; #Если ТолстыйКлиентОбычноеПриложение; отказ вне этого своего File-контекста.

Процедура ПриКопировании(ОбъектКопирования)
#Если ТолстыйКлиентОбычноеПриложение Тогда
    ЗаписьСчета85.ПроверитьКандидат85(ОбъектКопирования, "Источник", Документы.УчебныйСчет85.ПустаяСсылка());
    Если ОбъектКопирования.ЭтоНовый() Или ОбъектКопирования.Проведен <> Истина Тогда
        ВызватьИсключение "Копируется только собственный сохраненный исходный счет75";
    КонецЕсли;
    Маркер85 = ЗаписьСчета85.Маркер85("Копия");
    Номер = "";
    Дата = ОбъектКопирования.Дата;
    Количество85 = 3;
    Цена85 = 15;
    Сумма85 = Количество85 * Цена85;
    Основание85 = ОбъектКопирования.Ссылка;
#Иначе
    ВызватьИсключение "Только собственный ordinary File-стенд";
#КонецЕсли
КонецПроцедуры

Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
#Если ТолстыйКлиентОбычноеПриложение Тогда
    ЗаписьСчета85.ПроверитьСтенд85();
    Если ТипЗнч(ДанныеЗаполнения) <> Тип("ДокументСсылка.УчебныйСчет85") Или ДанныеЗаполнения.Пустая() Тогда
        ВызватьИсключение "Нужно реальное собственное основание-счет";
    КонецЕсли;
    Источник = ДанныеЗаполнения.ПолучитьОбъект();
    ЗаписьСчета85.ПроверитьКандидат85(Источник, "Источник", Документы.УчебныйСчет85.ПустаяСсылка());
    Если Источник.ЭтоНовый() Или Источник.Проведен <> Истина Тогда
        ВызватьИсключение "Основание еще не записано и не проведено";
    КонецЕсли;
    Маркер85 = ЗаписьСчета85.Маркер85("Основание");
    Номер = "";
    Дата = Источник.Дата;
    Количество85 = 1;
    Цена85 = 20;
    Сумма85 = Количество85 * Цена85;
    Основание85 = ДанныеЗаполнения;
#Иначе
    ВызватьИсключение "Заполнение недоступно вне ordinary File-стенда";
#КонецЕсли
КонецПроцедуры

Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
#Если ТолстыйКлиентОбычноеПриложение Тогда
    Попытка
        ЗаписьСчета85.ПроверитьРазрешение85(ЭтотОбъект, РежимЗаписи);
    Исключение
        Отказ = Истина;
        ВызватьИсключение;
    КонецПопытки;
#Иначе
    Отказ = Истина;
#КонецЕсли
КонецПроцедуры

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

ОбщиеФормы.ПультСчета85.Модуль

Толстый ordinary клиент; реальные own factories и события своих кнопок.

Перем СвояФорма85, Остановка85;

Процедура ПриОткрытии()
    Если Остановка85 <> Неопределено Тогда
        Возврат;
    КонецЕсли;
    Остановка85 = Истина;
    ЗаписьСчета85.ПроверитьСтенд85();
    Остановка85 = Ложь;
    Состояние85 = "Новая база: сначала Источник75, затем Копия45→90, затем Основание20. Запись подтверждается отдельно в каждом документе.";
КонецПроцедуры

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

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

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

Процедура ОткрытьКандидат85(Маршрут)
    Если Остановка85 = Истина Или (СвояФорма85 <> Неопределено И СвояФорма85.Открыта()) Тогда
        ВызватьИсключение "Сначала закройте собственную открытую форму; после ошибки продолжение запрещено";
    КонецЕсли;
    Попытка
        Снимок = ЗаписьСчета85.ПрочитатьВсе85();
        Если ЗаписьСчета85.НайтиШапку85(Снимок, ЗаписьСчета85.Маркер85(Маршрут)) <> Неопределено Тогда
            ВызватьИсключение "Этот собственный счет уже записан; дубль и автоматический retry запрещены";
        КонецЕсли;
        Источник = Документы.УчебныйСчет85.ПустаяСсылка();
        Если Маршрут = "Источник" Тогда
            Если Снимок.Шапки.Количество() <> 0 Тогда
                ВызватьИсключение "Исходный счет подготавливается только в действительно пустой базе";
            КонецЕсли;
            Объект = Документы.УчебныйСчет85.СоздатьДокумент();
            Объект.Маркер85 = ЗаписьСчета85.Маркер85("Источник");
            Объект.Дата = Дата(2026, 10, 10);
            Объект.Количество85 = 3;
            Объект.Цена85 = 25;
            Объект.Сумма85 = Объект.Количество85 * Объект.Цена85;
            Объект.Основание85 = Источник;
        Иначе
            СтрокаИсточника = ЗаписьСчета85.НайтиШапку85(Снимок, ЗаписьСчета85.Маркер85("Источник"));
            Если СтрокаИсточника = Неопределено Тогда
                ВызватьИсключение "Сначала вручную подтвердите запись собственного исходного счета75";
            КонецЕсли;
            Источник = СтрокаИсточника.Ссылка;
            Если Маршрут = "Копия" Тогда
                ОбъектИсточника = Источник.ПолучитьОбъект();
                Объект = ОбъектИсточника.Скопировать();
            Иначе
                Объект = Документы.УчебныйСчет85.СоздатьДокумент();
                Объект.Заполнить(Источник);
            КонецЕсли;
        КонецЕсли;
        ЗаписьСчета85.ПроверитьКандидат85(Объект, Маршрут, Источник);
        Если Не ЗаписьСчета85.РавныСнимки85(ЗаписьСчета85.ПрочитатьВсе85(), Снимок) Тогда
            ВызватьИсключение "Copy/Fill должны готовить память, а не скрыто записывать базу";
        КонецЕсли;
        Ключ = Новый УникальныйИдентификатор;
        КандидатФормы = Объект.ПолучитьФорму("Счет85", ЭтаФорма, Ключ);
        Если ТипЗнч(КандидатФормы) <> Тип("Форма") Или КандидатФормы.ВладелецФормы <> ЭтаФорма
            Или КандидатФормы.КлючУникальности <> Ключ Или КандидатФормы.Документ85 <> Объект Тогда
            ВызватьИсключение "Не получена форма именно своего кандидата счета";
        КонецЕсли;
        КандидатФормы.Подготовить85(ЭтаФорма, Маршрут, Источник, Снимок);
        КандидатФормы.Открыть();
        СвояФорма85 = КандидатФормы;
    Исключение
        Остановка85 = Истина;
        Состояние85 = "СТОП. Пульт больше не создает кандидатов; действительные записи и причины ошибки проверьте отдельно.";
        ВызватьИсключение;
    КонецПопытки;
КонецПроцедуры
ОбычноеПриложение

Конфигурация.МодульОбычногоПриложения

Native ПриНачалеРаботыСистемы0; получение и открытие своей общей формы.

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

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

  1. Пульт создает actual ДокументОбъект, Copy или Fill и получает именно его ordinary форму; она не записывает данные при подготовке.

  2. АвтонумерацияНеИспользовать оставляет номер пустым при открытии, при записи номер назначается metadata-автонумерацией. Readonly АвтоВремя показывается пользователю без выдуманного default.

  3. Первое проведение вызывает WriteInForm(Проведение) и native Object.Проведение, который готовит ровно одну собственную запись факта. BoolFalse не засчитывается как успех.

  4. ПриЗаписиПерепроводитьTrue применяется к уже проведенной копии: WriteInForm(Запись) при6×15 дает факт90 вместо45. РежимНеоперативный задан явно; native события не вызываются вручную.

  5. После native ПослеЗаписи вне завершенной транзакции снова читаются все собственные шапки/факты и GetObject. Сверяем Source75 и каждую другую старую строку, а не только текущую сумму.

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

  1. Суммы фактического собственного регистра после ручных шагов75/120/165/185, отдельно Source75/Copy90/Basis20.

  2. Без согласия, при duplicate/foreign basis, stale snapshot, False от WriteInForm или readback mismatch — явный отказ и sticky STOP, без automatic retry/cleanup.

  3. Все исходники проверены статически; платформа, CF compiler, UI, база, номер/время и transaction behavior фактически не запускались.

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

Ожидаемый будущий ручной результат: Source75 неизменен, Copy45→90, Basis20; три собственных проведенных документа и три active факта, общий итог185. Здесь actual1C/DB/UI/network/files/OS0, runtimeVerifiedFalse, backups0.

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

  1. Обычная форма и managed form extension — разные native owners. Здесь Форма.ВладелецФормы366, не Владелец и не managed ВладелецФормы7205.

  2. AutoTime readonly. ModeНеИспользовать сам сбрасывает время на0:00:00, но этот режим не присваивается форме и не предполагается по умолчанию.

  3. CopyingObjectParameter/BasisParameter содержат ссылки и служат проверенным контекстом этого маршрута. Код отдельно вызывает настоящие Copy/Fill; не обещает их автоматический вызов из setter.

  4. ПослеЗаписи вызывается после окончания транзакции; исключение нашего последующего readback не означает откат уже записанного документа. Транзакциями владеет платформа, собственные Begin/Commit/Rollback здесь не добавляются.

  5. Снимки и transient разрешение — ограничения конкретного учебного процесса, не криптографическая авторизация и не замена ролям. В другом коде или измененной CF обходы не исключены.

  6. После ошибки не запускайте форму вновь как retry. Нет delete/undo/post rollback/файловых резервных копий; требуется отдельное осознанное исследование только своего стенда.

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

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

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

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

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