Каждый специалист, работающий с конфигурациями «1С:Управление производственным предприятием» (УПП) или «1С:Комплексная автоматизация 1.1» на режиме РАУЗ (Расширенная аналитика учета затрат), рано или поздно сталкивается с пугающим явлением. При проведении обычного документа Отчет производства за смену (ОПЗС) или при запуске регламентного документа Расчет себестоимости выпуска (РСВ) система формирует движения по регистрам с «космическими» цифрами — триллионами, биллионами или даже квадриллионами рублей.
Такая ситуация парализует работу базы данных: СУБД (например, MS SQL Server) выдает ошибку переполнения числового поля (Arithmetic overflow error), проведение документов полностью блокируется, а себестоимость продукции становится невозможно рассчитать. Разберем детально физику этого процесса, выясним причины расхождения алгоритмов распределения и рассмотрим пошаговое руководство по устранению этой проблемы.
Для того чтобы понять, откуда берутся триллионы рублей при копеечной себестоимости сырья, обратимся к математике РАУЗ. В отличие от традиционного партионного учета, который рассчитывает себестоимость последовательно по цепочке документов, РАУЗ строит глобальную математическую модель. Все движения запасов и затрат за месяц представляются в виде системы линейных алгебраических уравнений (СЛУ) типа Ax = b.
Эта система уравнений решается в документе Расчет себестоимости методом итераций (чаще всего используется модифицированный метод Зейделя). В штатном режиме, когда исходные данные корректны, система сходится за 5–15 итераций, а погрешность (среднее отклонение решений) стремится к нулю. Однако, если в данных допущена грубая ошибка, система уравнений теряет устойчивость и начинает расходиться.
При расхождении СЛУ на каждой последующей итерации стоимости начинают умножаться на колоссальные коэффициенты (происходит деление на сверхмалые величины или отрицательные остатки). На 50-й итерации (это жестко зашитый лимит в коде 1С) алгоритм аварийно прекращает расчет, оставляя в базе данных те самые астрономические суммы. Лог расчета себестоимости при этом выглядит следующим образом:
Выполненное количество итераций расчета стоимости: 50
Полученное среднее отклонение решений: 0.274704...
Обнаружены отрицательные остатки по регистрам учета затрат!
Расчет себестоимости может быть выполнен некорректно.
Показатель отклонения 0.274704 — это огромная величина (в норме должно быть меньше 0.00001). Это прямой сигнал о том, что математическая модель "сломалась".
Многих пользователей удивляет: почему триллионы появляются в движениях нового документа ОПЗС еще до того, как запущен расчет себестоимости за месяц? Дело в том, что при проведении ОПЗС в режиме РАУЗ система пытается рассчитать предварительную себестоимость списания затрат на выпуск.
Если в прошлых периодах или в текущем месяце по аналитике списываемой номенклатуры уже накопилась «грязь» (например, огромная сумма при нулевом количестве), документ ОПЗС подхватывает эту искаженную среднюю стоимость и умножает её на количество выпуска. В результате мы получаем мгновенную блокировку базы данных из-за переполнения разрядности регистров.
Рассмотрим основные причины, которые приводят к краху математической модели РАУЗ, и способы их локализации.
Это самая распространенная причина расхождения СЛУ. Если на складе или в незавершенном производстве (НЗП) по конкретному ключу аналитики образовался минус по количеству (например, списали 10 единиц материала, когда на остатке было только 5), РАУЗ пытается рассчитать среднюю стоимость единицы.
Математически деление накопленной стоимости на отрицательное количество переворачивает знаки в системе уравнений, лишая матрицу диагонального преобладания. Метод итераций сходит с ума, лавинообразно увеличивая значения сумм с каждым шагом.
Решение:
Необходимо полностью искоренить количественные минусы. Для этого выполним следующие действия:
Ведомость по учету затрат (или Ведомость по учету МПЗ) за проблемный период.Раздел учета, Склад, Номенклатура, Характеристика, Ключ аналитики.КоличествоКонечныйОстаток < 0.В РАУЗ учет ведется одновременно по управленческому и регламентированному учету. Каждое движение привязывается к ключу аналитики, который содержит в себе два поля: Подразделение (управленческая структура) и ПодразделениеОрганизации (регламентированная структура).
Если в справочнике Подразделения для управленческого подразделения не задано сопоставление с соответствующим подразделением организации (или наоборот), система не может корректно связать затраты. Возникает ситуация, когда затраты приходят по одному ключу аналитики, а выпуск отражается по другому. Это разрывает цепочку распределения и ломает расчет.
Решение:
Свяжем подразделения организации с управленческими подразделениями:
Подразделения (управленческий учет).Подразделения организаций.Зацикливание (кольцевые зависимости) возникает, когда затраты распределяются по кругу. Рассмотрим классический пример петли:
Если в настройках распределения не заданы жесткие правила оценки встречного выпуска, алгоритм РАУЗ будет бесконечно гонять стоимость по кругу, увеличивая ее до астрономических масштабов на каждой итерации.
Решение:
Для разрыва кольцевых зависимостей в РАУЗ предусмотрен специальный регистр сведений Встречный выпуск продукции (услуг). Проанализируем встречные потоки и настроим правила:
Предприятие — Учет политики — Встречный выпуск продукции (услуг).По расчетной стоимости или укажем фиксированные Цены номенклатуры. Это позволит алгоритму РАУЗ зафиксировать стоимость на одном из этапов и разорвать бесконечный цикл расчетов.В некоторых случаях, когда исправить учетные ошибки оперативно не удается, разработчики прибегают к программному «лечению» симптомов. В общем модуле УчетЗатрат можно доработать процедуру ВыполнитьРаспределениеЗатрат.
Суть доработки заключается в принудительном пресечении роста сумм при итерациях. Программа отслеживает появление сверхмалых коэффициентов распределения (например, меньше 0.000001) или отрицательных количеств в процессе итерационных циклов и принудительно обнуляет их, не позволяя стоимости расти до триллионов.
Ниже приведен концептуальный пример кода, который может быть внедрен разработчиком для предотвращения переполнения разрядности при расчете:
// Фрагмент модификации алгоритма распределения в общем модуле УчетЗатрат
Процедура ВыполнитьРаспределениеЗатрат(ТаблицаЗатрат, ПараметрыРасчета) Экспорт
// Перебор итераций расчета стоимости
Для Итерация = 1 По 50 Цикл
// [Штатный код расчета стоимостей]
// Внедряемый защитный механизм против раздувания сумм
Для Каждого СтрокаДанных Из ТаблицаЗатрат Цикл
Если СтрокаДанных.Стоимость > 1000000000000 Тогда // Ограничиваем триллионные суммы
СтрокаДанных.Стоимость = 0;
СтрокаДанных.СтоимостьРег = 0;
СтрокаДанных.ПревышенЛимитСтоимости = Истина;
КонецЕсли;
// Защита от деления на сверхмалые остатки количества
Если Абс(СтрокаДанных.Количество) < 0.00001 И СтрокаДанных.Стоимость <> 0 Тогда
СтрокаДанных.Стоимость = 0;
СтрокаДанных.СтоимостьРег = 0;
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Важное предупреждение: такой патч является «костылем». Он помогает провести документ Расчет себестоимости без падения СУБД в ошибку переполнения, но он маскирует реальные проблемы учета. Истинная себестоимость продукции при использовании таких заглушек все равно будет искажена. Настоятельно рекомендуем решать проблему через зачистку данных, а не через модификацию кода.
Чтобы избежать внезапного появления триллионных сумм в будущем, рекомендуем придерживаться следующих правил в повседневной работе:
Тестирование и исправление ключей аналитики (меню «Сервис» — «Настройка учета»). Она находит осиротевшие, некорректные или дублирующиеся ключи РАУЗ и приводит их в порядок.Расчет себестоимости выпуска. Если вы видите, что количество итераций равно 50, а отклонение больше нуля — не игнорируйте это, ищите причину расхождения системы уравнений по описанному выше алгоритму.