В процессе разработки и сопровождения самописных обработок для выгрузки данных во внешние системы (например, системы складского учета WMS или интернет-магазины) программисты часто сталкиваются с ситуацией, когда документы за текущий день не попадают в выборку. Это создает серьезные задержки в бизнес-процессах: склад не видит свежих заказов, а операторы вынуждены передавать данные вручную.
Рассмотрим детально причины возникновения этой проблемы на примере реального кейса, проанализируем программный код и найдем способы корректного получения данных «секунда в секунду».
Первым делом проанализируем, как в коде устанавливается период выгрузки. Зачастую разработчики используют стандартные методы объектной модели для настройки периода, но допускают ошибки в обработке пустых значений или границ времени.
Посмотрим на типичный некорректный пример:
НастройкаПериода.УстановитьПериод(Период.ДатаНачала, ?(Период.ДатаОкончания='0001-01-01', Период.ДатаОкончания, КонецДня(Период.ДатаОкончания)));
В данной строке мы видим попытку привести дату окончания к концу дня. Однако, если Период.ДатаОкончания не заполнена (равна пустой дате), система может вести себя непредсказуемо в зависимости от того, как далее этот период передается в запрос. Если выгрузка должна включать данные по текущий момент времени включительно, нам необходимо гарантировать, что граница периода установлена правильно.
Разберем более надежный вариант написания этого условия:
НастройкаПериода.УстановитьПериод(Период.ДатаНачала, ?(ЗначениеЗаполнено(Период.ДатаОкончания), КонецДня(Период.ДатаОкончания), КонецДня(ТекущаяДата())));
Использование функции КонецДня крайне важно, так как по умолчанию дата без указания времени воспринимается системой как 00:00:00 (начало дня). Если мы передадим в запрос дату «12.10.2023», то документы, созданные даже в одну секунду первого ночи этого же дня, могут не попасть в выборку.
Проанализируем текст запроса, который используется для получения данных из регистров накопления. В нем кроется наиболее вероятная причина «исчезновения» сегодняшних документов.
ВЫБРАТЬ
ТоварыНаСкладахОбороты.Номенклатура КАК Номенклатура,
ТоварыНаСкладахОбороты.Регистратор,
ТоварыНаСкладахОбороты.Регистратор.Номер,
ТоварыНаСкладахОбороты.Регистратор.Дата,
// ... расчет количества
ПОМЕСТИТЬ ВТ_Остатки
ИЗ
РегистрНакопления.ТоварыНаСкладах.Обороты(&ДатаНачала, &ДатаОкончания, Регистратор, &УсловиеСклад) КАК ТоварыНаСкладахОбороты
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладах
ПО ТоварыНаСкладахОбороты.Регистратор = ТоварыНаСкладах.Регистратор
// ... дополнительные условия соединения
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрНакопления.ПартииТоваровНаСкладах КАК ПартииТоваровНаСкладах
ПО ТоварыНаСкладахОбороты.Регистратор = ПартииТоваровНаСкладах.Регистратор
// ... дополнительные условия соединения
Выясним причину, по которой ВНУТРЕННЕЕ СОЕДИНЕНИЕ (INNER JOIN) с таблицей ПартииТоваровНаСкладах обрезает данные текущего дня. Во многих типовых и доработанных конфигурациях (например, УТ 10.3, КА 1.1) используется механизм отложенного проведения по партиям.
Это означает следующее:
ТоварыНаСкладах (количественный учет), чтобы оперативно отразить остаток на складе.ПартииТоваровНаСкладах (себестоимость) не создаются мгновенно. Они формируются либо специальной регламентной обработкой в конце дня, либо фоновым заданием с задержкой.Результат: Если мы используем ВНУТРЕННЕЕ СОЕДИНЕНИЕ, то запрос вернет только те записи, которые есть в ОБЕИХ таблицах. Поскольку в таблице партий данных за сегодня еще нет, весь результат по сегодняшним документам просто отсекается. Чтобы этого избежать, необходимо использовать ЛЕВОЕ СОЕДИНЕНИЕ.
Рассмотрим еще один важный аспект — расчет поля «Количество». В исходном коде часто встречается странная конструкция в блоке ВЫБОР:
ВЫБОР
КОГДА ТоварыНаСкладах.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход)
ТОГДА ЕСТЬNULL(ТоварыНаСкладахОбороты.КоличествоРасход, 0) + ЕСТЬNULL(ТоварыНаСкладахОбороты.КоличествоПриход, 0)
ИНАЧЕ ЕСТЬNULL(ТоварыНаСкладахОбороты.КоличествоРасход, 0) + ЕСТЬNULL(ТоварыНаСкладахОбороты.КоличествоПриход, 0)
КОНЕЦ КАК Количество
Проанализируем ситуацию: здесь и в случае прихода, и в случае расхода значения ресурсов суммируются. Это логическая ошибка. Если ваша цель — получить чистое изменение остатка или корректный оборот, знаки должны различаться. Для получения дельты (изменения) правильно использовать вычитание расхода из прихода.
Также использование виртуальной таблицы Обороты совместно с физической таблицей того же регистра через соединение по регистратору — это архитектурный антипаттерн. Это приводит к значительному замедлению запроса и потенциальному дублированию строк, если один и тот же товар встречается в документе несколько раз (например, по разным сериям или характеристикам).
Для того чтобы гарантированно захватить все документы, включая те, что записаны в последнюю секунду указанного периода, рекомендуется использовать объект Граница. Это исключает неоднозначность трактовки времени платформой.
Пример правильной передачи параметров в запрос на языке 1С:
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ ... ИЗ РегистрНакопления.ТоварыНаСкладах.Обороты(&Начало, &Конец, , )";
КонечнаяДата = ?(ЗначениеЗаполнено(Объект.ДатаОкончания), КонецДня(Объект.ДатаОкончания), КонецДня(ТекущаяДата()));
// Используем Границу для включения документов, попадающих на последнюю секунду
Запрос.УстановитьПараметр("Начало", НачалоДня(Объект.ДатаНачала));
Запрос.УстановитьПараметр("Конец", Новый Граница(КонечнаяДата, ВидГраницы.Включая));
Подведем итоги и сформируем алгоритм исправления обработки выгрузки:
КонецДня. Если выгрузка работает в автоматическом режиме, используйте ТекущаяДата() в качестве значения по умолчанию.ВНУТРЕННЕЕ СОЕДИНЕНИЕ на ЛЕВОЕ СОЕДИНЕНИЕ, если вы обращаетесь к вспомогательным регистрам (партии, затраты), которые могут заполняться не сразу.Обороты), не соединяя ее без крайней необходимости с основной физической таблицей регистра. Все нужные поля (Склад, Номенклатура) уже есть в измерениях виртуальной таблицы.Соблюдение этих правил позволит вашей системе интеграции работать стабильно, а данные в Biglit или любую другую внешнюю систему будут попадать мгновенно после проведения документов в 1С.