В практике программирования на платформе 1С:Предприятие нередко встречается ситуация, когда процедура, запущенная вручную пользователем, отрабатывает безупречно, а то же самое действие в рамках регламентного задания выдает некорректный результат. Эта проблема часто кажется «мистической», так как код один и тот же, входных параметров нет, а данные на выходе различаются. Проанализируем подобную ситуацию на примере выгрузки остатков на FTP в базе 10.3 (Обычное приложение) на SQL-сервере.
Первое, что мы должны рассмотреть — это принципиальная разница между ручным запуском и выполнением задания сервером. Когда вы запускаете процедуру кнопкой, код выполняется в контексте клиентского приложения (в случае обычных форм). Когда работает регламентное задание, код исполняется исключительно на стороне сервера под правами специальной системной учетной записи (например, USR1CV8).
Разберем основные факторы, влияющие на результат в разных контекстах:
ТекущаяДата() на клиенте берет время с локального компьютера пользователя, а на сервере — с серверной машины. Если между ними есть рассинхронизация даже в несколько секунд, остатки в регистре на «границе» времени могут отличаться.НайтиПоНаименованию внутри регламентного задания — это зона высокого риска. Посмотрим на типичную ошибку в коде:
// Небезопасный код для регламентного задания
СкладОбъект = Справочники.Склады.НайтиПоНаименованию("Основной склад");
СписокГрупп = Новый СписокЗначений;
СписокГрупп.Добавить(Справочники.Номенклатура.НайтиПоНаименованию("Товары в наличии"));
Проанализируем этот фрагмент. Если в базе существуют дубликаты с одинаковым названием или невидимыми спецсимволами, сервер 1С может вернуть другую ссылку, отличную от той, которую выбирает клиентское приложение. Кроме того, поиск может зависеть от настроек языка и сортировки (Collation) в SQL-базе.
Рассмотрим структуру запроса, который часто используется для выгрузки остатков. Проблема может скрываться в самой логике получения данных на конкретную дату.
ВЫБРАТЬ
ВсеДанные.Номенклатура КАК Номенклатура,
СУММА(ВсеДанные.Остаток) - СУММА(ВсеДанные.Резерв) КАК СвободныйОстаток
ИЗ
(ВЫБРАТЬ
ТоварыНаСкладахОстатки.Номенклатура,
ТоварыНаСкладахОстатки.КоличествоОстаток КАК Остаток,
0 КАК Резерв
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаОстатков, Склад = &Склад) КАК ТоварыНаСкладахОстатки
) КАК ВсеДанные
СГРУППИРОВАТЬ ПО
ВсеДанные.Номенклатура
Если параметр &ДатаОстатков передается как пустая дата или некорректно инициализируется в фоновом задании, запрос вернет актуальные остатки на текущий момент. Однако, если в коде &ДатаОстатков вычисляется как КонецДня(ТекущаяДата()), а регламентное задание запускается в 08:00 утра, результат может быть непредсказуемым из-за специфики работы виртуальных таблиц остатков.
Выясним причину, которая чаще всего оказывается верной в «мистических» случаях. Если вы изменили расписание (например, на 07:45), консоль заданий рапортует об успешном выполнении в 07:45, а в итоговом файле на FTP вы видите время 08:00 и старые данные — ваш файл перезаписывает другая база.
Рассмотрим этот механизм подробнее:
Чтобы исключить влияние внешних факторов и ошибок контекста, выполним следующие шаги:
Шаг 1. Расширенное логирование. Добавим в процедуру выгрузки запись отладочной информации прямо в текстовый файл или в журнал регистрации. Нам важно знать параметры среды в момент выполнения фонового задания.
Процедура ВыгрузитьОстаткиНаФТП()
// Записываем параметры окружения для диагностики
ЗаписьЖурналаРегистрации("ВыгрузкаОстатков", УровеньЖурналаРегистрации.Информационный, , ,
"Имя компьютера: " + ИмяКомпьютера() +
", База: " + СтрокаСоединенияИнформационнойБазы() +
", Пользователь ОС: " + ИмяПользователя());
// Код получения остатков...
КонецПроцедуры
Шаг 2. Отказ от поиска по наименованию. Заменим НайтиПоНаименованию на поиск по уникальному идентификатору или коду, который не меняется. Это гарантирует, что и на сервере, и на клиенте будет выбран один и тот же склад.
// Правильный способ получения ссылки в регламентном задании
СсылкаНаСклад = Справочники.Склады.ПолучитьСсылку(Новый УникальныйИдентификатор("550e8400-e29b-41d4-a716-446655440000"));
Шаг 3. Проверка прав доступа. Проанализируем права пользователя, под которым запускается сервер 1С. Если выгрузка идет во временную папку на диске перед отправкой на FTP, убедитесь, что у учетной записи USR1CV8 есть права на удаление и перезапись файлов в этом каталоге. Часто бывает, что старый файл просто не может быть удален, и новые данные дописываются в конец или не записываются вовсе.
Шаг 4. Использование блокировки регламентных заданий. В консоли администрирования серверов 1С проверим все подозрительные базы. Для всех тестовых и архивных баз обязательно должен быть установлен флаг «Блокировка регламентных заданий включена».
Разберем итог: если данные в файле не соответствуют времени запуска задания в рабочей базе, это явный признак работы стороннего процесса. Всегда проверяйте СтрокаСоединенияИнформационнойБазы() внутри кода задания — это самый быстрый способ обнаружить «базу-призрак», которая портит ваши отчеты. Совмещая этот метод с отказом от ненадежных способов поиска объектов (по наименованию), вы обеспечите стабильную и предсказуемую работу ваших регламентных механизмов.