Почему при копировании документа в 1С не копируются реквизиты и как это исправить?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При разработке и доработке конфигураций на платформе 1С:Предприятие 8.3 разработчики часто сталкиваются с ситуацией: пользователь копирует существующий документ, но часть реквизитов (например, касса, склад, подразделение или дата) не переносится в новый документ или сбрасывается в значения по умолчанию. Рассмотрим подробнее, почему так происходит, как устроена механика копирования документов платформой и как правильно обработать копирование в коде.

Как работает стандартное копирование документов в 1С

Разберем базовые правила платформы 1С:Предприятие при создании документа путем копирования:

  1. Автоматическое копирование данных: Платформа по умолчанию копирует значения всех реквизитов шапки и табличных частей исходного документа.
  2. Очистка системных полей: Поле Ссылка создается заново, а поле Номер очищается, чтобы при записи новому документу присвоился следующий по порядку номер.
  3. Заполнение даты: В скопированный документ платформа автоматически подставляет текущую дату и время системы.
  4. Статус нового объекта: Скопированный документ до момента первой записи считается новым. Это означает, что метод ЭтоНовый() для него всегда возвращает значение Истина.

Выясним главную причину проблемы: если реквизит (например, Касса) копируется платформой, но при открытии формы оказывается пустым или перезаписанным, значит, в коде модуля формы или модуля объекта срабатывает алгоритм инициализации нового документа, который затирает скопированные данные.

Анализ проблемы на примере обычных форм

Проанализируем типичную ситуацию из практики. В документе при открытии формы нового документа прописана установка автора и кассы по умолчанию:


Процедура ПередОткрытием(Отказ, СтандартнаяОбработка)
    Если ЭтоНовый() Тогда
        Автор = ТекПользователь;
        Касса = Автор.Касса3;
    КонецЕсли;
КонецПроцедуры

На первый взгляд логика кажется верной: подставлять кассу текущего пользователя только для новых документов. Однако, поскольку скопированный документ также является новым (метод ЭтоНовый() возвращает Истина), данная процедура срабатывает и при копировании. В результате значение реквизита Касса, перенесенное из исходного документа, перекрывается значением по умолчанию или очищается, если касса у пользователя не заполнена.

Решение проблемы для обычных форм

Чтобы разграничить создание абсолютно нового документа и создание документа копированием, необходимо проверить параметр формы ПараметрОбъектКопирования.

Разберем по шагам правильное оформление кода:

  1. В модуле объекта (если требуется принудительно сохранить дату исходного документа или скорректировать реквизиты) используем обработчик ПриКопировании.
  2. В модуле формы в процедуре ПередОткрытием добавляем проверку заполнения объекта копирования.

Посмотрим на пример итогового кода в модуле объекта:


Процедура ПриКопировании(ОбъектКопирования)
    // Если по бизнес-логике требуется скопировать дату исходного документа:
    ЭтотОбъект.Дата = ОбъектКопирования.Дата;
    ЭтотОбъект.Касса = ОбъектКопирования.Касса;
КонецПроцедуры

Посмотрим на пример кода в модуле обычной формы:


Процедура ПередОткрытием(Отказ, СтандартнаяОбработка)
    Если ЭтоНовый() Тогда
        Автор = ТекПользователь;
        
        // Проверяем, что документ создается с нуля, а не путем копирования
        Если НЕ ЗначениеЗаполнено(ПараметрОбъектКопирования) Тогда
            Касса = Автор.Касса3;
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Важное примечание по поводу даты: Принудительное копирование даты из старого документа в новый требует осторожности. Если исходный документ был создан в прошлом месяце или году, новый документ получит старую дату, что может привести к случайному проведению документа в закрытом периоде или ошибкам контроля остатков.

Решение проблемы согласно стандартам разработки 1С (Управляемые формы)

В современных конфигурациях на управляемых формах и архитектуре БСП (Библиотека Стандартных Подсистем) заполнение реквизитов рекомендуется выносить из модулей форм в модуль объекта.

  1. Заполнение по умолчанию: Выполняется в обработчике ОбработкаЗаполнения модуля объекта. Данный обработчик вызывается платформой автоматически при создании нового документа, но не вызывается при копировании.
  2. Очистка лишних данных при копировании: Выполняется в обработчике ПриКопировании модуля объекта. В нем обычно очищают реквизиты, которые не должны переноситься (например, статусы согласования, ссылки на внешние файлы или ответственные за проведение).
  3. Проверка в управляемой форме: Если инициализация происходит в форме (в событии ПриСозданииНаСервере), факт копирования проверяется через параметры формы:

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Проверяем, что это новый объект и он создан НЕ копированием
    Если Объект.Ссылка.Пустая() И НЕ Параметры.Ключ.Заполнено() И НЕ ЗначениеЗаполнено(Параметры.ЗначениеЗаполнения) Тогда
        // Заполнение реквизитов по умолчанию для нового документа
    КонецЕсли;

КонецПроцедуры

Соблюдение этих правил позволяет избежать затирания данных при копировании документов и обеспечивает корректную работу бизнес-логики системы.

← На главную