При разработке механизмов интеграции в 1С программисты часто сталкиваются с загадочным поведением системы: один и тот же код выдает разные результаты в зависимости от того, запущен он пользователем вручную или выполнен сервером в рамках регламентного задания. Одной из самых ярких иллюстраций этой проблемы является загрузка курсов валют, когда значение курса внезапно «скачет» на несколько порядков (например, в 1000 раз). В этой статье мы подробно разберем причины возникновения такой ситуации и найдем способы её решения.
Для начала давайте разберем, что происходит в момент запуска обработки. Когда вы нажимаете кнопку «Выполнить» в форме обработки, код исполняется в контексте Текущего сеанса пользователя. В этом случае система использует региональные настройки вашей операционной системы (Windows или Linux), ваш кэш и ваши параметры сеанса.
Когда же обработка запускается через РегламентныеЗадания (или через механизм дополнительных отчетов и обработок по расписанию), она выполняется в Фоновом задании на стороне сервера. Фоновое задание работает под учетной записью службы сервера 1С (например, USR1CV8). У этой учетной записи свои региональные настройки, свой профиль и полное отсутствие интерактивного контекста.
Это самая частая причина изменения порядка чисел. Давайте проанализируем, как 1С интерпретирует строку при преобразовании в число. Рассмотрим пример: с сайта загружена строка "34.1245".
В интерактивном сеансе пользователя настройки ОС могут быть установлены таким образом, что точка является разделителем дробной части. Функция Число("34.1245") вернет 34,1245. Все хорошо.
Однако на сервере 1С региональные настройки часто установлены в значение «Русский (Россия)», где:
В этом случае сервер может интерпретировать "34.1245" крайне непредсказуемо. Если в строке три знака после точки, сервер воспримет её как «34 тысячи 124 с копейками». Если знаков больше, функция преобразования может либо выдать ошибку, либо «проглотить» точку, превратив дробное число в огромное целое, которое затем при делении на кратность даст неверный порядок. Или наоборот, если код ожидает определенный формат, а получает другой, запятая может сдвинуться на три знака влево или вправо.
Решение: Никогда не полагайтесь на стандартное преобразование типов при работе с внешними данными. Используйте принудительную замену разделителей.
// Безопасное преобразование строки в число
Функция СтрокуВЧисло(ЗначениеСтрокой) Экспорт
// Убираем неразрывные пробелы и другие разделители групп
ЧистаяСтрока = СтрЗаменить(ЗначениеСтрокой, Символы.НПП, "");
ЧистаяСтрока = СтрЗаменить(ЧистаяСтрока, " ", "");
// Приводим к единому стандарту (заменяем точку на запятую)
ЧистаяСтрока = СтрЗаменить(ЧистаяСтрока, ".", ",");
Попытка
Возврат Число(ЧистаяСтрока);
Исключение
Возврат 0;
КонецПопытки;
КонецФункции
В системе 1С курс валюты всегда привязан к справочнику Валюты и его реквизиту Кратность. Рассмотрим ситуацию: курс валюты на сайте указан за 1 единицу, а в вашей базе для «тяжелых» валют (например, Узбекский сум или старый Японский иена) установлена кратность 1000.
При ручном запуске программист мог случайно зашить в код использование кратности из формы, которая инициализирована значением «1». В фоновом же задании форма не создается, и код может брать данные напрямую из справочника, где установлена «1000». Если в алгоритме записи в регистр сведений КурсыВалют происходит деление или умножение на кратность без проверки контекста, возникает ошибка в 1000 раз.
Выясним причину через код записи. Правильная логика должна выглядеть так:
МенеджерЗаписи = РегистрыСведений.КурсыВалют.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Период = ТекущаяДата();
МенеджерЗаписи.Валюта = СсылкаНаВалюту;
// Курс, полученный с сайта (за 1 единицу)
КурсССайта = 34.1245;
// Обязательно учитываем кратность из справочника
МенеджерЗаписи.Курс = КурсССайта;
МенеджерЗаписи.Кратность = СсылкаНаВалюту.Кратность;
МенеджерЗаписи.Записать();
Если же вы записываете курс, уже пересчитанный с учетом кратности, убедитесь, что вы не делаете это дважды.
Проанализируем ситуацию, когда обработка использует ПараметрыСеанса. В фоновом задании параметры сеанса инициализируются через модуль сеанса. Если логика загрузки курса опирается на какой-то параметр (например, ПараметрыСеанса.ТекущийПользователь или кастомные настройки), который в фоновом задании имеет значение по умолчанию или Неопределено, это может привести к ветвлению алгоритма (выбору другого источника данных или другой формулы расчета).
Чтобы не гадать, почему значения различаются, необходимо выполнить отладку именно серверного контекста. Рассмотрим шаги:
В момент остановки проверьте содержимое переменной, содержащей строку с курсом, и результат работы функции Число(). Вы сразу увидите разницу в интерпретации знаков.
Чтобы избежать подобных проблем в будущем, рекомендуем придерживаться следующих правил:
ЧтениеJSON или ЧтениеXML, 1С обрабатывает типы данных согласно стандартам этих форматов, где точка всегда является разделителем дробной части, независимо от локали ОС.Строка(Число, "L=en_US").Таким образом, корень проблемы почти всегда лежит в неявном преобразовании типов и различии региональных настроек между сессией интерактивного пользователя и системной службой сервера 1С. Внимательное отношение к преобразованию строк и учет кратности валют позволит вам создавать стабильные интеграции.