Как в 1С:Бухгалтерия 3.0 определить, что документ отправлен через Диадок, и защитить его от изменений?

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия Бухгалтерский учет IT и автоматизация бизнеса
← На главную

При организации совместной работы старых конфигураций (например, 1С 7.7) и современных решений на базе 1С 8.3 (БП 3.0) часто возникает критическая проблема: документ, уже отправленный контрагенту через ЭДО Диадок, может быть случайно перезаписан при очередной синхронизации данных. Это приводит к расхождению данных в учетной системе и в электронном документе, что недопустимо с точки зрения налогового учета.

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

Вариант 1: Использование модуля в виде расширения

Если в вашей информационной базе Диадок установлен как расширение, это значительно упрощает задачу. Разработчики из Контура предусмотрели специальные метаданные для хранения связей. Проанализируем структуру хранения данных:

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

Рассмотрим пример функции, которую можно разместить в общем модуле для проверки блокировки:


Функция ДокументЗаблокированЭДО(ДокументСсылка) Экспорт
    // Проверка для случая использования расширения
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Диадок_СостоянияДокументов.Состояние КАК Состояние
        |ИЗ
        |   РегистрСведений.Диадок_СостоянияДокументов КАК Диадок_СостоянияДокументов
        |ГДЕ
        |   Диадок_СостоянияДокументов.Объект = &ДокументСсылка";
    
    Запрос.УстановитьПараметр("ДокументСсылка", ДокументСсылка);
    Результат = Запрос.Выполнить();
    
    Если НЕ Результат.Пустой() Тогда
        Выборка = Результат.Выбрать();
        Выборка.Следующий();
        // Если статус не пустой и не "Не сформирован", блокируем
        Возврат Истина; 
    КонецЕсли;
    
    Возврат Ложь;
КонецФункции

Вариант 2: Использование внешней обработки Диадок

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

Выясним, как именно записываются эти данные. При отправке документа модуль создает запись в регистре сведений ДополнительныеСведения. В качестве объекта выступает ссылка на документ, а в качестве свойства — специально созданный дополнительный реквизит с именем ИдентификаторДокументаВДиадок (или аналогичным техническим именем DiadocMessageId).

Проанализируем алгоритм проверки для этого случая:

  1. Нам нужно найти программное имя свойства, которое использует Диадок.
  2. Выполнить запрос к регистру ДополнительныеСведения по паре "Объект" + "Свойство".
  3. Если значение (строковый идентификатор) заполнено, документ считается отправленным.

Пример кода для проверки дополнительных сведений:


Функция ЕстьИдентификаторДиадок(СсылкаНаДокумент)
    СвойствоИД = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("ИдентификаторДокументаВДиадок");
    
    Если СвойствоИД.Пустая() Тогда
        Возврат Ложь;
    КонецЕсли;
    
    ЗначениеСведения = РегистрыСведений.ДополнительныеСведения.Получить(Новый Структура("Объект, Свойство", СсылкаНаДокумент, СвойствоИД)).Значение;
    
    Возврат ЗначениеЗаполнено(ЗначениеСведения);
КонецФункции

Вариант 3: Анализ макетов интеграции (Интеграционный модуль)

Для более глубокой настройки можно изучить внутреннюю логику самой обработки Диадок. В макете КонтурДиадокИнтеграцияБП30 содержится текст запросов, которые модуль использует для формирования списков документов "К отправке".

Если мы проанализируем функцию ПолучитьТекстЗапросаДляСпискаПакетовНаОтправкуПоМассивуВидовПакетов(), то увидим, как разработчики Контура отфильтровывают уже отправленные документы. Обычно это делается через временную таблицу ВТ_ОтправленныеДокументы, которая собирает данные из вышеупомянутых регистров. Мы можем использовать аналогичную логику в своем коде проверки.

Реализация надежной защиты от изменений

Чтобы защитить документ от изменений, которые приходят из 1С 7.7, недостаточно просто вывести предупреждение. Нужно внедрить проверку непосредственно в процесс записи объекта. Лучшим местом для этого является Подписка на событие ПередЗаписью.

Создадим подписку для документов РеализацияТоваровУслуг и СчетФактураВыданный. В обработчике события крайне важно учитывать флаг ОбменДанными.Загрузка. Рассмотрим, почему это важно.

Когда данные приходят из "семерки", платформа 1С устанавливает Загрузка = Истина. По умолчанию многие проверки в 1С в этом режиме отключаются. Нам же нужно, чтобы наша проверка на Диадок РАБОТАЛА даже при загрузке. Посмотрим на пример реализации обработчика:


Процедура ПередЗаписьюДокументаДляЭДО(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
    
    // Если документ новый, проверять нечего
    Если Источник.ЭтоНовый() Тогда
        Возврат;
    КонецЕсли;
    
    // Проверяем наличие связи с Диадоком
    Если ДокументЗаблокированЭДО(Источник.Ссылка) Тогда
        
        // Если это интерактивное изменение пользователем
        Если НЕ Источник.ОбменДанными.Загрузка Тогда
            ТекстСообщения = "Документ уже отправлен через Диадок и заблокирован для редактирования!";
            ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстСообщения, Источник.Ссылка);
            Отказ = Истина;
        Иначе
            // Если это загрузка из 1С 7.7
            // Здесь мы можем либо вызвать Отказ = Истина (тогда обмен прервется с ошибкой)
            // Либо просто проигнорировать изменения, не записывая их
            ЗаписьЖурналаРегистрации("ОбменДанными", УровеньЖурналаРегистрации.Предупреждение, 
                Источник.Метаданные(), Источник.Ссылка, "Попытка изменения отправленного в Диадок документа проигнорирована.");
            Отказ = Истина; 
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

Дополнительные рекомендации по синхронизации

Помимо программного запрета в БП 3.0, проанализируем ситуацию на стороне 1С 7.7 и в правилах конвертации. Чтобы избежать постоянных ошибок в логах обмена, рекомендуется внести изменения в правила выгрузки:

  1. Фильтрация на стороне источника: Если в 1С 7.7 есть возможность помечать документы, которые уже ушли в "восьмерку" и были там подписаны, лучше исключать их из выборки для выгрузки.
  2. Использование API: В сложных случаях можно использовать методы API Диадока (например, GetEntityContent) для оперативной проверки статуса документа напрямую на сервере Контура, если локальные регистры в 1С по какой-то причине не обновились.
  3. Визуализация: Для удобства пользователей в форме списка документов БП 3.0 рекомендуется настроить Условное оформление. Выделяйте серым цветом или иконкой "Замок" те строки, по которым уже создан пакет ЭДО. Это предотвратит попытки ручного редактирования и лишние вопросы сотрудников.

Таким образом, комбинируя поиск по служебным регистрам расширения и использование дополнительных сведений для внешних обработок, мы создаем надежный барьер, сохраняющий юридическую значимость наших электронных документов.

← На главную