При работе в программах семейства «1С:Предприятие 8» пользователи часто используют копирование существующих документов (клавиша F9) в качестве удобного шаблона для быстрого ввода новых данных. Однако стандартное поведение платформы при копировании автоматически заменяет дату исходного документа на текущую компьютерную или рабочую дату. Это сделано для того, чтобы новые документы по умолчанию создавались текущим днем.
Тем не менее в практике бухгалтерского и управленческого учета нередко возникает задача: сделать так, чтобы при копировании любого документа (или определенной группы документов) полностью сохранялась дата исходного документа-источника. В этой статье мы подробно разберем, как решить эту задачу наиболее корректным и безопасным с точки зрения архитектуры 1С способом, а также проанализируем неочевидные риски, о которых обязательно нужно предупредить бизнес-пользователей.
Если мы заглянем в модуль объекта практически любого типового документа, то в процедуре ПриКопировании() мы увидим принудительную установку даты. Обычно это выглядит следующим образом: Дата = ТекущаяДата() или заполнение рабочей датой системы.
Первая идея, которая может прийти в голову начинающему разработчику, — зайти в каждый документ конфигурации и переопределить это поведение непосредственно в коде модуля каждого конкретного объекта. Разберем, почему делать так категорически не рекомендуется:
Ниже мы рассмотрим правильный, изящный способ решения этой задачи, который полностью сохраняет конфигурацию на стандартной поддержке.
В платформе «1С:Предприятие 8» реализован мощный механизм подписок на события. Он позволяет «перехватывать» стандартные события объектов (такие как запись, проведение, копирование, заполнение) и выполнять собственный программный код в общих модулях без изменения самих объектов метаданных.
Проанализируем по шагам, как реализовать подписку на событие для принудительного сохранения даты при копировании.
Для начала нам понадобится общий серверный модуль, в котором будет располагаться процедура-обработчик нашей подписки. Если в вашей конфигурации уже есть подходящий неглобальный общий модуль (например, ОбщегоНазначенияСервер или аналогичный кастомный модуль для доработок), вы можете использовать его. Если нет — создадим новый.
Общие -> Общие модули._РаботаСДокументамиСобытия.В созданном общем модуле напишем процедуру, которая будет перезаписывать дату нового документа датой исходного. Обратите внимание, что процедура обязательно должна иметь ключевое слово Экспорт.
Процедура ПриКопированииДокументаДляСохраненияДаты(Источник, ОбъектКопирования) Экспорт
// Проверяем, что объект копирования существует и у него заполнена дата
Если ЗначениеЗаполнено(ОбъектКопирования) И ЗначениеЗаполнено(ОбъектКопирования.Ссылка) Тогда
// Перезаписываем дату нового документа датой из источника копирования
Источник.Дата = ОбъектКопирования.Дата;
КонецЕсли;
КонецПроцедуры
Разберем параметры этой процедуры:
Источник — это новый, только что созданный в памяти документ (объект типа ДокументОбъект), который формируется в результате копирования.ОбъектКопирования — это ссылка на оригинальный документ-источник, с которого и производится копирование.Теперь свяжем нашу процедуру со стандартным событием копирования документов в системе.
Общие -> Подписки на события._СохранитьДатуПриКопированииДокументов.ДокументСсылка и установите флаг на самом верхнем уровне ДокументОбъект (в этом случае автоматически выберутся все документы системы).ПриКопировании._РаботаСДокументамиСобытия.ПриКопированииДокументаДляСохраненияДаты.У разработчиков часто возникает логичный вопрос: «В стандартных модулях документов уже прописана очистка даты или установка текущей рабочей даты в процедуре ПриКопировании(). Нужно ли удалять этот стандартный код, чтобы он не конфликтовал с нашей подпиской?»
Выясним причину, почему удалять или комментировать стандартный код не нужно. Платформа 1С строго регламентирует последовательность выполнения обработчиков событий:
Таким образом, наша подписка на событие гарантированно отработает последней. Она просто перезапишет дату, которую установил типовой механизм, вернув исходное значение из документа-копии. Никаких конфликтов или зацикливаний при этом не происходит.
Несмотря на то, что технически задача решается очень быстро и просто, её внедрение в реальную рабочую базу несет в себе скрытые риски для ведения учета. Прежде чем отдавать эту доработку пользователям, обязательно обсудите с главным бухгалтером следующие моменты:
Если тотальное сохранение дат через подписку признано слишком рискованным, рассмотрим альтернативный вариант решения на уровне конкретных форм документов. Мы можем сохранять дату исходного документа только тогда, когда это действительно нужно пользователю, выводя диалоговое окно с вопросом.
Для реализации этой логики используется параметр формы нового документа ЗначениеКопирования, который содержит ссылку на исходный документ. На клиенте в модуле формы документа мы можем обработать этот сценарий:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Проверяем, что документ открывается в режиме копирования
Если Параметры.Свойство("ЗначениеКопирования") И ЗначениеЗаполнено(Параметры.ЗначениеКопирования) Тогда
// Мы можем сохранить ссылку на исходный документ во временный реквизит формы
// для последующего анализа или вывода вопроса пользователю при открытии
ОбъектКопированияСсылка = Параметры.ЗначениеКопирования;
КонецЕсли;
КонецПроцедуры
Этот способ более трудоемок, так как требует вмешательства в формы конкретных документов (или использования механизма расширений для управляемых форм), но он гораздо безопаснее для стабильности учета в базе данных.