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