При проведении документов оплаты от клиентов (например, Поступление безналичных ДС или Приходный кассовый ордер) в программах «1С:Комплексная автоматизация 2.4» или «1С:ERP Управление предприятием» пользователи часто сталкиваются с неожиданным сбоем. Система выдает системное сообщение об ошибке в обработчике проведения, ссылаясь на невозможность выполнения метода Записать() для движений документа.
Что примечательно, если снять флаг Проведено банком, документ без проблем сохраняется в системе, но, разумеется, не формирует никаких движений по регистрам и бухгалтерских проводок. Стоит вернуть этот флаг обратно и попытаться провести документ — транзакция завершается аварийно. Давайте подробно разберем, почему возникает эта ошибка, как устроены внутренние механизмы платформы в этот момент и как исправить ситуацию безболезненно для учета.
Для детального анализа ситуации нам потребуется запустить базу в режиме отладки на сервере. При включенной отладке стек вызовов покажет точное место возникновения исключения. Ошибка происходит в общем модуле ОперативныеВзаиморасчетыСервер внутри процедуры ЗаполнитьОперативныеВзаиморасчеты.
Проанализируем проблемный участок кода, на котором спотыкается платформа:
// Область РасчетФактическойЗадолженности в модуле ОперативныеВзаиморасчетыСервер
Если СтрокаОплаты.ПорядокОперации < СтрокаОтгрузкиПоставки.ПорядокОперации Тогда
// Алгоритм распределения авансов
КонецЕсли;
Причиной падения системы с ошибкой «Операции сравнения на больше-меньше допустимы только для значений совпадающих примитивных типов» является то, что в одной из сравниваемых строк (чаще всего в таблице отгрузок) реквизит ПорядокОперации имеет значение NULL (или Неопределено). Платформа 1С:Предприятие не умеет сравнивать строковый тип данных с системным типом NULL на больше/меньше, что и вызывает прерывание транзакции проведения.
В рамках новой архитектуры взаиморасчетов, представленной в ERP 2.4 и КА 2.4, распределение платежей и отгрузок происходит автоматически по методу FIFO в режиме реального времени при проведении документов. Чтобы программа знала точную хронологическую последовательность операций, используется служебный строковый реквизит ПорядокОперации, который пишется в регистры накопления группы «Расчеты с клиентами» и «Расчеты с поставщиками» (в частности, в регистр РасчетыСКлиентамиПоСрокам).
Эта служебная строка формируется по шаблону и обычно содержит информацию в следующем формате:
[Дата в формате ГГГГММДД][ТипОперации(Приоритет)][Время][УникальныйИдентификатор/НомерДокумента]
Пример заполненного порядка операции: 201907094235959330М00-000262. За счет строкового сравнения таких кодов система мгновенно выстраивает документы в правильную FIFO-цепочку.
Если по какой-то причине в базе данных у одного из документов реализации или корректировки это поле не заполнено (в запросе возвращается NULL), то при попытке провести любой последующий платеж по этой аналитике учета (клиент, договор, направление деятельности) система будет падать на этапе сопоставления расчетов.
Выделим три основные практические причины появления пустого значения ПорядокОперации в регистрах:
ОбменДанными.Загрузка = Истина). Движения по регистрам формируются без вызова процедур заполнения оперативных взаиморасчетов.Рассмотрим несколько способов устранения этой проблемы — от исправления данных в пользовательском режиме до временного программного обхода ошибки разработчиком.
Прежде всего нам необходимо понять, по какому именно партнеру и договору база содержит поврежденные записи взаиморасчетов. Посмотрим на примере отладки, как локализовать сбойный документ:
ОперативныеВзаиморасчетыСервер на строке с ошибкой.СтрокаОплаты.Регистратор и СтрокаОтгрузкиПоставки.Регистратор. Один из этих документов и будет нашей проблемной сделкой.РасчетыСКлиентамиПоСрокам. Добавьте группировку по регистратору и выведите колонку Порядок зачета или Порядок операции. Настройте отбор, где Порядок операции не заполнен или равен NULL.Также вы можете быстро найти пустые значения с помощью простого консольного запроса:
ВЫБРАТЬ
Расчеты.Регистратор КАК ПроблемныйДокумент,
Расчеты.АналитикаУчетаПоПартнерам.Партнер КАК Партнер,
Расчеты.ПорядокОперации КАК ПорядокОперации
ИЗ
РегистрНакопления.РасчетыСКлиентамиПоСрокам КАК Расчеты
ГДЕ
Расчеты.ПорядокОперации ЕСТЬ NULL
ИЛИ Расчеты.ПорядокОперации = ""
После того как сбойный документ обнаружен (например, это оказалась старая Реализация товаров и услуг или Документ ввода остатков), проанализируем его реквизиты:
ПорядокОперации в регистре.Если вам необходимо срочно провести платежные поручения, а времени на поиск поврежденного документа в закрытых периодах прошлых лет сейчас нет, можно временно обезопасить программный код от падения в транзакции проведения. Для этого создадим расширение конфигурации и добавим безопасное приведение типов в сравнении.
Рассмотрим, как заменить исходный небезопасный код в общем модуле на отказоустойчивый:
// Внедряем безопасное приведение к строке для исключения NULL
ПорядокОплаты = ?(СтрокаОплаты.ПорядокОперации = NULL, "", СтрокаОплаты.ПорядокОперации);
ПорядокОтгрузки = ?(СтрокаОтгрузкиПоставки.ПорядокОперации = NULL, "", СтрокаОтгрузкиПоставки.ПорядокОперации);
Если ПорядокОплаты < ПорядокОтгрузки Тогда
// Алгоритмы распределения оплат по FIFO продолжат работу без аварийного завершения
КонецЕсли;
Важное предупреждение: Данный программный обход является лишь «тушением пожара» для оперативного проведения текущих платежей. Он не исправляет накопленные ошибки ведения FIFO-очереди в прошлых периодах. После проведения срочных документов обязательно найдите и перепроведите поврежденную накладную или документ ввода остатков, как описано в Шаге 1.