Как предотвратить потерю ДокументаОснования при ручной правке документов, созданных на основании, в 1С?

Программист 1С v8.3 (Управляемые формы) 1С:Розница Торговля и дистрибуция
← На главную

При работе в системе 1С пользователи часто сталкиваются с необходимостью создавать новые документы на основании уже существующих. Этот механизм «Ввод на основании» значительно упрощает работу, автоматически заполняя часть информации и устанавливая логическую связь между документами. Однако иногда возникает ситуация, когда после создания документа на основании и последующей ручной правки некоторых его реквизитов, связь с ДокументомОснованием теряется. Документ перестаёт считаться введённым на основании, а также не отображается в стандартном отчёте «Связанные документы». Давайте вместе разберёмся, почему это происходит и как можно эффективно решить данную проблему.

Анализируем проблему: почему пропадает ДокументОснование?

Ситуация, когда ДокументОснование исчезает, может проявляться по-разному. Рассмотрим основные признаки, которые позволяют нам выявить корень проблемы:

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

Возникновение таких проблем чаще всего связано с тем, как платформа 1С и разработчик конфигурации обрабатывают связи между документами и изменение их реквизитов.

Глубокое погружение: механизмы, влияющие на ДокументОснование

Чтобы эффективно решить проблему, мы должны понимать, какие механизмы платформы и конфигурации могут влиять на поведение ДокументаОснования. Рассмотрим подробнее основные факторы.

  1. Бизнес-логика в обработчиках событий

    Основная причина, по которой ДокументОснование пропадает при изменении некоторых реквизитов (например, Контрагента), кроется в программном коде конфигурации. При изменении ключевых реквизитов часто срабатывают обработчики событий, такие как ПриИзменении реквизита формы или методы, вызываемые в процедуре ОбработкаЗаполнения.

    Например, при изменении Контрагента система может сбросить не только Статью затрат, но и ДокументОснование. Это логично с точки зрения бизнес-процессов: если мы меняем контрагента, то исходный документ-основание (который, возможно, был связан с предыдущим контрагентом) может перестать быть актуальным для нового контрагента. Разработчики конфигурации часто реализуют такую логику для поддержания целостности данных. Если в этой логике не предусмотрено явное сохранение или переопределение ДокументаОснования при определённых условиях, оно может быть очищено.

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

  2. Свойство "Заполнять из данных заполнения"

    Это свойство реквизита, устанавливаемое в конфигураторе, позволяет платформе автоматически заполнять его значение, используя параметр ДанныеЗаполнения в процедуре ОбработкаЗаполнения. Когда документ создаётся на основании другого, ДанныеЗаполнения обычно содержат ссылку на документ-основание.

    Если это свойство установлено, платформа будет пытаться заполнить реквизит самостоятельно. То, что ДокументОснование показывается как Неопределено в отладчике, может быть связано с тем, что:

    • Отладка происходит до момента фактического присвоения значения реквизиту системой или в коде.
    • Мы смотрим на реквизит в контексте, где он ещё не был заполнен из ДанныхЗаполнения или был очищен последующей логикой.

    Хотя свойство автоматического заполнения полезно, оно может конфликтовать с нашей собственной логикой в ОбработкаЗаполнения, если мы не учитываем его поведение.

  3. Ограничения по типу реквизита "ДокументОснование"

    Реквизит ДокументОснование (если он есть в шапке документа или в табличной части) может иметь составной тип данных. Это означает, что он может хранить ссылки на различные типы документов (например, "ДокументСсылка.РеализацияТоваровУслуг", "ДокументСсылка.ПриходныйКассовыйОрдер" и т.д.).

    Критически важно: если тип документа, на основании которого мы пытаемся создать новый документ, не включен в список разрешённых типов для реквизита ДокументОснование (это настраивается в конфигураторе в свойстве "Тип" реквизита), то ссылка на документ-основание не будет сохранена. При попытке присвоения платформа просто проигнорирует его или очистит. Для корректной работы необходимо убедиться, что требуемый тип документа добавлен в ОписаниеТипов реквизита ДокументОснование.

  4. "ДокументОснование" в табличных частях ПКО и РКО

    Для сложных документов, таких как Приходный кассовый ордер (ПКО) и Расходный кассовый ордер (РКО), информация о документе-основании может храниться не в одном реквизите шапки документа, а в отдельной табличной части. Это особенно актуально, когда один кассовый ордер может быть создан на основании нескольких документов (например, нескольких документов поступления или заказов).

    В пользовательском режиме эта табличная часть может быть скрыта, если основание только одно, но на уровне данных информация всё равно сохраняется в ней. Если при создании РКО на основании "Оприходования" документ не попадает в "Связанные документы", это может указывать на то, что ссылка на основание не заполняется корректно именно в этой табличной части, а не в реквизите шапки (которого может и не быть в явном виде).

  5. Проблема с отчётом "Связанные документы"

    Отчёт "Связанные документы" использует установленные связи между документами. Эти связи могут быть явно определены через реквизит ДокументОснование (если он ссылочного типа), или же они могут быть установлены программно в регистрах сведений, которые хранят информацию о взаимосвязях.

    Если ДокументОснование очищается или не заполняется должным образом (например, из-за несовпадения типов, ошибок в логике заполнения или некорректного сохранения в табличной части), связь не будет установлена или будет разорвана. Соответственно, документ не появится в этом отчёте.

Пошаговое решение проблемы

Теперь, когда мы понимаем потенциальные причины, давайте разработаем алгоритм действий для решения проблемы пропадания ДокументаОснования.

  1. Шаг 1: Отладка и анализ кода в процедурах заполнения и изменения

    Первым делом нам необходимо точно выяснить, в какой момент и почему ДокументОснование теряет своё значение. Для этого мы будем использовать отладчик.

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

    Цель: Идентифицировать место в коде, где происходит очистка или некорректное присвоение ДокументаОснования.

  2. Шаг 2: Проверка и расширение типа реквизита "ДокументОснование"

    Если отладка показывает, что ДокументОснование присваивается, но не сохраняется, вероятно, проблема в неверном типе.

    1. В конфигураторе откройте документ, который создаётся на основании (например, РКО).
    2. Перейдите на вкладку «Данные».
    3. Найдите реквизит, который должен хранить ссылку на документ-основание. Это может быть реквизит в шапке (например, ДокументОснование или Основание) или в табличной части (например, ДокументОснование табличной части РасшифровкаПлатежа).
    4. Кликните по свойству «Тип» этого реквизита.
    5. Убедитесь, что в списке разрешённых типов данных присутствует ДокументСсылка.ОприходованиеТоваров (или любой другой тип документа-основания, который вы используете). Если его нет, добавьте его.
    6. Обновите конфигурацию базы данных.

    Пример изменения типа реквизита:

    Предположим, у нас есть реквизит Основание в документе РКО. В его свойствах "Тип" мы должны убедиться, что разрешены ссылки на все документы, которые могут быть основаниями для РКО, в том числе и на наш Документ.ОприходованиеТоваров.

    Цель: Убедиться, что реквизит ДокументОснование может хранить ссылку на нужный нам тип документа.

  3. Шаг 3: Корректное заполнение ДокументаОснования в процедуре ОбработкаЗаполнения

    Мы должны явно установить ДокументОснование, используя параметр ДанныеЗаполнения.

    1. Откройте модуль объекта документа, который создаётся (например, РКО).
    2. Найдите или создайте процедуру ОбработкаЗаполнения(ДанныеЗаполнения).
    3. В этой процедуре нам нужно получить ссылку на документ-основание и присвоить её соответствующему реквизиту. Если ДанныеЗаполнения не Неопределено и является ссылкой, мы можем использовать её.

    Пример кода для модуля объекта РКО:

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

    Цель: Гарантировать, что ДокументОснование корректно присваивается в момент создания документа.

  4. Шаг 4: Учет хранения ДокументаОснования в табличных частях (для ПКО/РКО)

    Как мы уже выяснили, для некоторых документов (ПКО, РКО) ДокументОснование может храниться не в шапке, а в табличной части. Это требует особого подхода при заполнении.

    1. В процедуре ОбработкаЗаполнения, вместо присвоения реквизиту шапки, нам нужно создать новую строку в соответствующей табличной части и заполнить её реквизит, который является ДокументомОснованием.
    2. Обычно это табличная часть, которая содержит детали платежа или расшифровку. Найдите её в конфигураторе.

    Пример (уже включен в предыдущий код, но акцентируем внимание):

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

    Цель: Обеспечить корректное сохранение ссылки на основание в нужной структуре документа.

  5. Шаг 5: Проверка и модификация обработчиков событий формы

    Если ДокументОснование очищается после изменения других реквизитов (например, Контрагента), нам нужно проанализировать обработчики ПриИзменении для этих реквизитов.

    1. Откройте модуль формы документа, который создаётся.
    2. Найдите процедуру ПриИзменении для реквизита, который вызывает очистку (например, КонтрагентПриИзменении).
    3. Внимательно изучите логику. Если там происходит явная очистка ДокументаОснования без необходимости, рассмотрите возможность её удаления или модификации.
    4. Если очистка необходима по бизнес-логике (например, при смене контрагента действительно нужно сбросить все старые связи), но при этом мы хотим сохранить информацию об основании для отчётов, мы можем:
      • Добавить дополнительный реквизит (например, ИсходноеОснование) и сохранять в нём ссылку на ДокументОснование, переданное при вводе.
      • Или пересмотреть логику так, чтобы очистка ДокументаОснования происходила только при определённых условиях, или чтобы после очистки предлагалось выбрать новое основание, если это применимо.

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

    Цель: Предотвратить нежелательную очистку ДокументаОснования при изменении других реквизитов или обеспечить его повторное заполнение/сохранение в альтернативном виде.

  6. Шаг 6: Тестирование и отчет "Связанные документы"

    После всех изменений необходимо тщательно протестировать функциональность.

    1. Создайте несколько документов на основании.
    2. Попробуйте изменить различные реквизиты, которые ранее приводили к потере ДокументаОснования.
    3. Убедитесь, что ДокументОснование теперь сохраняется.
    4. Проверьте, что созданные документы корректно отображаются в отчёте «Связанные документы». Если они всё ещё не появляются, возможно, отчёт использует другие механизмы связи (например, специализированные регистры сведений), которые также требуют доработки.
      • Если отчёт не видит связь, а реквизит ДокументОснование заполнен, проверьте, какие регистры сведений заполняет типовая конфигурация для поддержания связей (например, регистр сведений "ВзаимосвязиДокументов" или подобные). Возможно, потребуется модифицировать или дополнить их заполнение.

    Цель: Подтвердить, что проблема полностью решена, и все связи сохраняются корректно.

Решение проблемы с пропаданием ДокументаОснования требует комплексного подхода, включающего анализ бизнес-логики, проверку типов данных, корректное заполнение в процедуре ОбработкаЗаполнения и внимательную работу с обработчиками событий. Следуя этим шагам, мы сможем восстановить и поддерживать целостность связей между документами в вашей системе 1С.

← На главную