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

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

В практической работе с конфигурациями на платформе 1С:Предприятие (особенно в комплексных исторических системах, таких как УПП 1.3 или КА 1.1) пользователи и администраторы периодически сталкиваются с необъяснимым на первый взгляд явлением. Документ, созданный на основании (например, корректировка заказа, реализация товаров или корректировка реализации), имеет время проведения раньше, чем сам документ-основание (например, заказ покупателя). На оси времени «потомок» оказывается в прошлом по отношению к своему «родителю».

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

Выясняем причину: как это происходит в базе данных

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

  1. Менеджер создает документ-основание — например, ЗаказПокупателя. Допустим, это происходит утром в 08:31:00. Документ успешно записывается и проводится.
  2. Спустя несколько часов (например, в 12:04:00) на основании этого заказа создается подчиненный документ — скажем, РеализацияТоваровУслуг или КорректировкаРеализации. Система связывает этот документ с заказом через ссылку GUID. Подчиненный документ записывается со своим текущим временем — 12:04:00.
  3. Еще позже (в 12:16:00) менеджеру по служебной необходимости требуется внести изменения в исходный ЗаказПокупателя (например, изменить количество, цену или просто перезаполнить какой-то реквизит). Менеджер нажимает кнопку «Провести».
  4. Поскольку проведение выполняется в текущий момент времени, платформа задействует механизм оперативного проведения. Система автоматически перезаписывает время документа-основания на текущее системное время сервера — то есть на 12:16:00.

В результате этой цепочки действий в базе данных оказывается следующая картина:

С точки зрения логики платформы 1С все корректно: документы связаны ссылочной связью. Но с точки зрения бизнес-логики и проведения по регистрам учета хронология нарушена. Получается, что отгрузка товара произошла раньше, чем сам заказ поступил в систему.

Как расследовать такие инциденты с помощью Журнала регистрации

Для того чтобы доказать пользователям, что документ действительно был перепроведен позже, нам потребуется обратиться к Журналу регистрации (ЖР). Именно там хранится вся история изменения объектов.

При анализе Журнала регистрации обратите внимание на следующие моменты:

  1. Найдите записи по уникальному идентификатору или номеру проблемного документа-основания.
  2. Обратите внимание на транзакции с событием Данные. Изменение и Данные. Проведение.
  3. В колонке Представление данных вы увидите первоначальное представление объекта (например, Заказ покупателя №001 от 19.02.2019 08:31:00), в то время как в колонке Дата/Время события ЖР будет зафиксировано время фактического проведения (например, 19.02.2019 12:16:48). Это неопровержимо доказывает факт смещения времени документа в результате повторных действий пользователя.

Как автоматически выявлять такие аномалии в базе данных

Для регулярного мониторинга состояния базы данных и поиска нарушений хронологии мы можем разработать простой отчет или воспользоваться консолью запросов. Нам необходимо сопоставить даты документов в парах «родитель — потомок».

Рассмотрим пример запроса, который находит расходные накладные, проведенные раньше своих заказов-оснований:


ВЫБРАТЬ
    Реализация.Ссылка КАК ПодчиненныйДокумент,
    Реализация.Дата КАК ДатаПодчиненного,
    Реализация.Сделка КАК ДокументОснование,
    Реализация.Сделка.Дата КАК ДатаОснования,
    Реализация.Ответственный КАК Ответственный
ИЗ
    Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
    Реализация.Проведен = ИСТИНА
    И Реализация.Сделка.Проведен = ИСТИНА
    И Реализация.Дата < Реализация.Сделка.Дата
    И Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода

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

Как решить проблему и предотвратить её появление в будущем

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

Способ 1. Программный запрет оперативного перепроведения документов при наличии подчиненных

Самым надежным решением является внедрение программной проверки. Мы можем создать подписку на событие ПередЗаписью для интересующих нас документов-оснований (например, заказов покупателей, поступлений товаров и услуг). Задача проверки — определить, проводится ли документ оперативно, и есть ли у него уже введенные на основании документы. Если подчиненные документы найдены, мы должны заблокировать проведение и выдать пользователю предупреждение.

Разберем пример реализации такой процедуры в общем модуле:


Процедура ПроверитьХронологиюПередЗаписью(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт

    // Проверяем только при реальном проведении
    Если РежимЗаписи <> РежимЗаписиДокумента.Проведение Тогда
        Возврат;
    КонецЕсли;

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

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

Способ 2. Автоматический перевод в неоперативный режим при повторном проведении

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

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


Процедура ПередЗаписьюДокументаДляСохраненияВремени(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт

    Если РежимЗаписи = РежимЗаписиДокумента.Проведение Тогда
        // Если документ уже был проведен ранее, принудительно переводим проведение в неоперативный режим
        Если Источник.Проведен Тогда
            РежимПроведения = РежимПроведенияДокумента.Неоперативный;
        КонецЕсли;
    КонецЕсли;

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

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

Способ 3. Организационные и интерфейсные ограничения

Если внесение изменений в программный код конфигурации нежелательно, мы можем минимизировать риски административными методами:

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

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

← На главную