При разработке и доработке конфигураций на платформе 1С:Предприятие 8.3 разработчики часто сталкиваются с ситуацией: пользователь копирует существующий документ, но часть реквизитов (например, касса, склад, подразделение или дата) не переносится в новый документ или сбрасывается в значения по умолчанию. Рассмотрим подробнее, почему так происходит, как устроена механика копирования документов платформой и как правильно обработать копирование в коде.
Разберем базовые правила платформы 1С:Предприятие при создании документа путем копирования:
Ссылка создается заново, а поле Номер очищается, чтобы при записи новому документу присвоился следующий по порядку номер.ЭтоНовый() для него всегда возвращает значение Истина.Выясним главную причину проблемы: если реквизит (например, Касса) копируется платформой, но при открытии формы оказывается пустым или перезаписанным, значит, в коде модуля формы или модуля объекта срабатывает алгоритм инициализации нового документа, который затирает скопированные данные.
Проанализируем типичную ситуацию из практики. В документе при открытии формы нового документа прописана установка автора и кассы по умолчанию:
Процедура ПередОткрытием(Отказ, СтандартнаяОбработка)
Если ЭтоНовый() Тогда
Автор = ТекПользователь;
Касса = Автор.Касса3;
КонецЕсли;
КонецПроцедуры
На первый взгляд логика кажется верной: подставлять кассу текущего пользователя только для новых документов. Однако, поскольку скопированный документ также является новым (метод ЭтоНовый() возвращает Истина), данная процедура срабатывает и при копировании. В результате значение реквизита Касса, перенесенное из исходного документа, перекрывается значением по умолчанию или очищается, если касса у пользователя не заполнена.
Чтобы разграничить создание абсолютно нового документа и создание документа копированием, необходимо проверить параметр формы ПараметрОбъектКопирования.
Разберем по шагам правильное оформление кода:
ПриКопировании.ПередОткрытием добавляем проверку заполнения объекта копирования.Посмотрим на пример итогового кода в модуле объекта:
Процедура ПриКопировании(ОбъектКопирования)
// Если по бизнес-логике требуется скопировать дату исходного документа:
ЭтотОбъект.Дата = ОбъектКопирования.Дата;
ЭтотОбъект.Касса = ОбъектКопирования.Касса;
КонецПроцедуры
Посмотрим на пример кода в модуле обычной формы:
Процедура ПередОткрытием(Отказ, СтандартнаяОбработка)
Если ЭтоНовый() Тогда
Автор = ТекПользователь;
// Проверяем, что документ создается с нуля, а не путем копирования
Если НЕ ЗначениеЗаполнено(ПараметрОбъектКопирования) Тогда
Касса = Автор.Касса3;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Важное примечание по поводу даты: Принудительное копирование даты из старого документа в новый требует осторожности. Если исходный документ был создан в прошлом месяце или году, новый документ получит старую дату, что может привести к случайному проведению документа в закрытом периоде или ошибкам контроля остатков.
В современных конфигурациях на управляемых формах и архитектуре БСП (Библиотека Стандартных Подсистем) заполнение реквизитов рекомендуется выносить из модулей форм в модуль объекта.
ОбработкаЗаполнения модуля объекта. Данный обработчик вызывается платформой автоматически при создании нового документа, но не вызывается при копировании.ПриКопировании модуля объекта. В нем обычно очищают реквизиты, которые не должны переноситься (например, статусы согласования, ссылки на внешние файлы или ответственные за проведение).ПриСозданииНаСервере), факт копирования проверяется через параметры формы:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Проверяем, что это новый объект и он создан НЕ копированием
Если Объект.Ссылка.Пустая() И НЕ Параметры.Ключ.Заполнено() И НЕ ЗначениеЗаполнено(Параметры.ЗначениеЗаполнения) Тогда
// Заполнение реквизитов по умолчанию для нового документа
КонецЕсли;
КонецПроцедуры
Соблюдение этих правил позволяет избежать затирания данных при копировании документов и обеспечивает корректную работу бизнес-логики системы.