При ведении учета материально-производственных запасов на счете 10 в конфигурации «1С:Бухгалтерия предприятия 3.0» пользователи нередко сталкиваются с ситуацией, когда при списании материалов программа выдает ошибку о нехватке остатков либо списывает партии, по которым в стандартных отчетах остатков нет. Если проанализировать виртуальную таблицу остатков или сформировать отчет с максимальной детализацией, можно увидеть, что по одной и той же номенклатуре и партии одновременно висят положительные и отрицательные остатки одинакового объема, которые не «схлопываются» между собой.
Рассмотрим природу возникновения этой ошибки, разберем методы диагностики проблемы в базе данных и пошагово изучим способы восстановления корректного учета.
Главная техническая причина подобного поведения кроется в особенностях работы платформы «1С:Предприятие» с небалансовыми измерениями регистра бухгалтерии Хозрасчетный, в частности с измерением Подразделение.
На уровне СУБД и внутренней логики платформы значение NULL (полное отсутствие значения в поле) и пустая ссылка определенного ссылочного типа (Справочник.Подразделения.ПустаяСсылка) представляют собой два принципиально разных значения. Когда для конкретного счета бухгалтерского учета или конфигурации в целом отключен учет по подразделениям (например, база работает в редакции ПРОФ, где нет учета по обособленным подразделениям на счетах затрат и ТМЦ), платформа ожидает, что в измерении Подразделение будет записано строго значение NULL.
Если в результате некорректных действий или сбоев часть движений была сформирована со значением NULL, а часть — с пустой ссылкой на справочник подразделений, виртуальная таблица остатков регистра бухгалтерии группирует записи по каждому уникальному значению измерения отдельно. Для платформы строка с NULL и строка с пустой ссылкой не являются идентичными, поэтому остатки по приходу и расходу не сворачиваются в ноль. При попытке списания алгоритм проведения по ФИФО видит положительное сальдо по строке с одним значением измерения и списывает его, порождая новые разрывы.
Проанализируем типовые сценарии, приводящие к появлению пустых ссылок вместо NULL:
NULL при изменении настроек не происходит.NULL, если пользователь или модуль формы не выполнил явную очистку.РегистрБухгалтерииНаборЗаписей без проверки признаков учета по счету, могут подставлять пустое значение ссылки.Для выявления документов-регистраторов, сформировавших неверные проводки, выполним запрос не к виртуальной таблице остатков, а напрямую к физической таблице движений регистра бухгалтерии. Запустим консоль запросов и выполним следующий текст:
ВЫБРАТЬ
Хозрасчетный.Регистратор КАК Документ,
Хозрасчетный.Период КАК Период,
Хозрасчетный.СчетДт КАК СчетДт,
Хозрасчетный.ПодразделениеДт КАК ПодразделениеДт,
Хозрасчетный.СчетКт КАК СчетКт,
Хозрасчетный.ПодразделениеКт КАК ПодразделениеКт
ИЗ
РегистрБухгалтерии.Хозрасчетный КАК Хозрасчетный
ГДЕ
(Хозрасчетный.СчетДт В ИЕРАРХИИ (ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.Материалы))
ИЛИ Хозрасчетный.СчетКт В ИЕРАРХИИ (ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.Материалы)))
И (Хозрасчетный.ПодразделениеДт = ЗНАЧЕНИЕ(Справочник.Подразделения.ПустаяСсылка)
ИЛИ Хозрасчетный.ПодразделениеКт = ЗНАЧЕНИЕ(Справочник.Подразделения.ПустаяСсылка))
Результат запроса покажет список документов, в проводках которых присутствует пустая ссылка вместо требуемого системой значения NULL.
Самым надежным штатным способом устранения нестыковок логической структуры данных является процедура тестирования и исправления информационной базы.
В окне сообщений в ходе проверки платформа найдет несоответствия типов и выведет служебные сообщения: «Значение должно быть NULL. Сохранено значение NULL». Платформа самостоятельно заменит пустые ссылки на NULL в соответствии с метаданными счета.
Если информационная база имеет большой объем и регламент обслуживания не позволяет остановить работу пользователей для полного тестирования и исправления, устраним расхождение программно с помощью внешней обработки. Разберем пример кода, перезаписывающего движения с установкой признака обмена данными:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| Хозрасчетный.Регистратор КАК Регистратор
|ИЗ
| РегистрБухгалтерии.Хозрасчетный КАК Хозрасчетный
|ГДЕ
| (Хозрасчетный.ПодразделениеДт = ЗНАЧЕНИЕ(Справочник.Подразделения.ПустаяСсылка)
| ИЛИ Хозрасчетный.ПодразделениеКт = ЗНАЧЕНИЕ(Справочник.Подразделения.ПустаяСсылка))";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
НаборЗаписей = РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(Выборка.Регистратор);
НаборЗаписей.Прочитать();
Модифицирован = Ложь;
Для Каждого Запись Из НаборЗаписей Цикл
Если Запись.ПодразделениеДт = Справочники.Подразделения.ПустаяСсылка() Тогда
Запись.ПодразделениеДт = NULL;
Модифицирован = Истина;
КонецЕсли;
Если Запись.ПодразделениеКт = Справочники.Подразделения.ПустаяСсылка() Тогда
Запись.ПодразделениеКт = NULL;
Модифицирован = Истина;
КонецЕсли;
КонецЦикла;
Если Модифицирован Тогда
НаборЗаписей.ОбменДанными.Загрузка = Истина;
НаборЗаписей.Записать();
КонецЕсли;
КонецЦикла;
Использование свойства ОбменДанными.Загрузка = Истина критически важно: оно отключает запуск стандартных обработчиков проведения и проверок, позволяя скорректировать только битые поля регистра без изменения остальных движений документа.
После того как значения в физических записях регистра приведены к NULL, выполним обязательный пересчет итогов. Без пересчета итогов виртуальные таблицы продолжат выдавать неактуальные данные.
Для этого в режиме «1С:Предприятие» перейдем в раздел Администрирование → Обслуживание → Регламентные операции → Управление итогами и агрегатами. Выберем регистр Хозрасчетный и нажмем Пересчитать итоги (либо запустим режим пересчета итогов через утилиту «Тестирование и исправление» в Конфигураторе).
После завершения пересчета партии на счете 10 схлопнутся, а списание материалов при проведении документов начнет выполняться штатно.