При выполнении регламентной операции закрытия месяца в программе 1С:Управление нашей фирмой (УНФ) пользователи могут столкнуться с критической ошибкой: Microsoft OLE DB Driver for SQL Server: Ошибка арифметического переполнения при преобразовании numeric к типу данных numeric. HRESULT=80040E57. Эта ошибка прерывает расчет себестоимости и не позволяет получить финансовый результат. Разберем детально, почему это происходит и как исправить ситуацию.
Прежде всего, проанализируем, где именно возникает сбой. В 1С:УНФ расчет себестоимости реализован через решение Системы Линейных Уравнений (СЛУ). За это отвечает процедура РешитьСЛУ(). Программа не просто вычитает приходы из расходов, она строит математическую модель всех перемещений запасов и затрат за месяц.
Для решения этой системы используется итерационный метод (похожий на метод Гаусса-Зейделя или метод простых итераций). Суть его в том, что программа делает множество «проходов» (итераций), уточняя стоимость каждой единицы товара. В норме с каждой итерацией отклонение должно уменьшаться, стремясь к нулю. Однако при определенных данных система начинает расходиться: вместо уменьшения суммы начинают расти в геометрической прогрессии. В итоге число становится настолько огромным, что не помещается в тип данных numeric(23, 10), используемый в SQL-запросах 1С, что и вызывает переполнение.
Рассмотрим основные ситуации, которые приводят к математическому «взрыву» сумм:
Запасы зависла копеечная сумма без количественного остатка, алгоритм при делении суммы на бесконечно малое количество выдает сверхвысокие значения. В этом случае поможет автоматическое списание себестоимости товаров, у которых нет количества, что позволит устранить причину математической расходимости.Чтобы решить задачу, нам нужно понять, на какой именно позиции «спотыкается» расчет. Для предварительной диагностики, когда закрытие еще не выполнено, можно запустить анализ списания запасов с себестоимостью без закрытия месяца, чтобы увидеть аномальные суммы списания.
Если у вас есть навыки отладки, рекомендуется зайти в процедуру РешитьСЛУ() и посмотреть на состояние таблицы ТаблицаРешений на 3–5 итерации. Вы увидите, что по одной или нескольким строкам значения Сумма начали исчисляться миллионами или миллиардами. Запомните НомерУзла этой строки. По этому номеру в регистре сведений УзлыКорректировкиСтоимостиСписания вы найдете конкретную номенклатуру, характеристику и партию.
Самый правильный и надежный способ разорвать «петлю» — это исключить спорный документ из системы уравнений. Рассмотрим, как это сделать:
Если использование фиксированной стоимости невозможно, проанализируем движения в регистре накопления Запасы. Иногда достаточно изменить входящие данные на ничтожно малую величину, чтобы математический маятник перестал раскачиваться.
Как показывает практика, корректировка суммы остатка или прихода всего на 1 копейку может привести систему к сходимости. Для этого воспользуемся документом Корректировка регистров или универсальной обработкой для корректировки и чтения остатков, добавив 0.01 к сумме по проблемной номенклатуре на дату начала закрываемого месяца.
Обязательно убедитесь, что в периоде нет «красноты». Сформируйте отчет Остатки товаров с детализацией до всех измерений (Организация, Склад, Номенклатура, Характеристика, Партия, Заказ). Если вы видите отрицательное количество — это первоочередная цель для исправления. Отрицательные остатки делают матрицу коэффициентов СЛУ неустойчивой. Если проблема кроется в аналитике по партиям, рекомендуется использовать автоматическое заполнение партий в УНФ, чтобы восстановить корректный учет и сходимость алгоритма.
Программистам, пытающимся модифицировать типовой код, важно помнить: изменение типа данных в запросе с ЧИСЛО(23, 10) на ЧИСЛО(32, 10) обычно не помогает. Это лишь немного отодвигает момент падения (на одну-две итерации позже), но не устраняет причину расходимости. Проблема не в разрядности, а в том, что алгоритм не находит решения.
Вместо этого можно внедрить проверку внутри цикла итераций в процедуре РешитьСЛУ():
Если МаксимальноеОтклонение > 1000000000000 Тогда // Лимит в триллион
ТекстОшибки = "Обнаружена расходимость расчета по узлу " + СтрокаПроблемногоУзла;
ВызватьИсключение ТекстОшибки;
КонецЕсли;
Это позволит программе прерваться раньше и выдать понятное сообщение пользователю, вместо системной ошибки SQL.
Резюмируем: Ошибка переполнения в УНФ — это всегда сигнал о логической или математической ошибке в цепочке документов. Ищите «петли», устраняйте отрицательные остатки и используйте механизм Фиксированной стоимости для стабилизации расчета. Если же вам необходимо увидеть финансовые результаты до устранения ошибки, вы можете сформировать отчет по валовой прибыли в учетных ценах, который работает даже без выполненного закрытия месяца.