Переход с обычных форм (например, в конфигурации «Управление торговлей 10.3») на управляемые формы («Комплексная автоматизация 2.x» или «ERP Управление предприятием») часто вызывает трудности у начинающих разработчиков. Типичный пример — задача фиксации даты первого проведения документа. Код, который отлично работал в обычной форме, в управляемом приложении начинает вызывать назойливое предупреждение системы: «Документ изменен. Провести или нет?».
В этой статье мы подробно разберем причины возникновения этой ошибки, детально изучим транзакционный цикл записи документа и напишем надежный, отказоустойчивый код для решения этой задачи с учетом всех особенностей клиент-серверной архитектуры 1С.
Для начала проанализируем ситуацию и поймем, почему старый подход из «Управления торговлей 10.3» перестал работать в «Комплексной автоматизации».
В обычных формах работа велась напрямую с объектом базы данных, который находился в памяти клиента. В управляемом приложении архитектура кардинально изменилась: форма на клиенте работает с предварительно подготовленными данными — так называемыми данными формы (тип ДанныеФормыСтруктураСвойства), в то время как запись и проведение происходят на сервере с полноценным объектом (тип ДокументОбъект).
Когда вы пишете код модификации реквизитов внутри обработчиков формы (например, ПередЗаписьюНаСервере), происходят следующие процессы:
ДатаСоздания).Кроме того, если пользователь решит провести документ не из самой формы, а из списка документов (нажатием правой кнопки мыши или кнопкой на панели списка), то события формы вообще не будут вызваны! В результате ваш код просто проигнорируется, и дата первого проведения останется пустой.
Вывод: Любая бизнес-логика, которая должна гарантированно выполняться при записи или проведении объекта (независимо от того, откуда именно инициировано это действие), должна располагаться исключительно в Модуле объекта.
---
Давайте по шагам разберем, как реализовать эту задачу профессионально. Нам потребуется учесть четыре важнейших фактора:
Откройте конфигуратор, найдите нужный документ в дереве метаданных конфигурации «1С:Комплексная автоматизация» (или другой вашей управляемой системы), нажмите по нему правой кнопкой мыши и выберите «Открыть модуль объекта».
Добавим предопределенную процедуру ПередЗаписью. Именно здесь мы будем перехватывать момент проведения документа.
Рассмотрим структуру кода, который решает поставленные задачи:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// 1. Исключаем срабатывание кода при обмене данными.
// Если идет загрузка из другой базы, мы не должны менять исторические данные.
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// 2. Проверяем режим записи. Нам нужно только проведение.
// Также проверяем, заполнена ли уже дата создания.
// Если она заполнена, значит документ проводится не в первый раз, и мы ничего не меняем.
Если РежимЗаписи = РежимЗаписиДокумента.Проведение
И Не ЗначениеЗаполнено(ДатаСоздания) Тогда
// Используем функцию ТекущаяДатаСеанса() вместо ТекущаяДата().
// Это гарантирует корректную запись времени для пользователей из разных часовых поясов.
ДатаСоздания = ТекущаяДатаСеанса();
КонецЕсли;
КонецПроцедуры
Разберем подробнее ключевые моменты этого кода:
ОбменДанными.Загрузка — обязательный стандарт разработки под платформу «1С:Предприятие». Если его не указать, то при первой же синхронизации данных (например, с «1С:Бухгалтерией») даты проведения документов могут перезаписаться текущим временем.Не ЗначениеЗаполнено(ДатаСоздания) гарантирует, что дата будет установлена один раз. При повторном перепроведении документа условие вернет ложь, и дата создания останется неизменной.ТекущаяДатаСеанса() критически важен в клиент-серверной архитектуре. Функция ТекущаяДата() возвращает время физического сервера. Если сервер баз данных расположен, к примеру, в Москве, а пользователь проводит документ во Владивостоке, то обычная дата запишет московское время. Метод ТекущаяДатаСеанса() автоматически скорректирует время под часовой пояс запущенного сеанса пользователя.Если пользователь скопирует уже проведенный документ, система скопирует все его реквизиты, включая заполненное поле ДатаСоздания. В итоге у нового документа это поле будет заполнено еще до его первого проведения. Чтобы избежать этого бага, добавим обработчик события ПриКопировании в этот же модуль объекта:
Процедура ПриКопировании(ОбъектКопирования)
// Очищаем реквизит у нового скопированного документа.
// Присваиваем пустую дату ('00010101000000').
ДатаСоздания = '00010101000000';
КонецПроцедуры
Теперь при создании копии реквизит ДатаСоздания у нового документа сразу станет пустым, и при его первом проведении корректно отработает условие в процедуре ПередЗаписью.
---
Если вы хотите спроектировать систему на уровне лучших стандартов разработки 1С, рассмотрим более гибкие подходы к решению этой задачи. Внесение изменений непосредственно в структуру документов (добавление новых реквизитов) усложняет последующие обновления типовой конфигурации «1С:Комплексная автоматизация».
Вместо добавления реквизита внутрь самого документа, мы можем создать простой непериодический регистр сведений (например, назвать его ДатыПервогоПроведенияДокументов) со следующей структурой:
Документ (тип: ДокументСсылка).ДатаПервогоПроведения (тип: Дата).При таком подходе в процедуре ОбработкаПроведения (или в подписке на событие проведения) мы можем проверять наличие записи по нашему документу в этом регистре. Если записи нет — мы делаем движение по регистру и записываем туда текущую дату сеанса. Это позволяет оставить сам документ нетронутым, что значительно облегчит дальнейшую поддержку и обновление конфигурации.
Поскольку «1С:Комплексная автоматизация» построена на базе БСП (Библиотеки стандартных подсистем), в нее уже по умолчанию встроен мощный инструмент логирования любых изменений. Этот механизм называется «История изменений» (Версионирование).
Для решения вашей задачи вам может вообще не потребоваться писать код! Достаточно выполнить следующие действия в режиме «1С:Предприятие»:
После этого система автоматически будет сохранять точное время каждого проведения, автора проведения и измененные реквизиты. Вы всегда сможете открыть историю и увидеть точную дату и время самого первого проведения документа.