При работе в программе «1С:Бухгалтерия» бухгалтеры и системные администраторы иногда сталкиваются со странным поведением отчетов: на счете 41.01 (или любом другом аналитическом счете) зависают остатки, у которых не заполнена номенклатура или склад. При попытке списать эти остатки обычным документом «Операция, введенная вручную» программа отказывается «схлопывать» суммы. Вместо списания мы получаем развернутое сальдо — в отчете ОСВ появляются две строки: одна с плюсом, другая с минусом, но обе визуально выглядят как пустые.
В этой статье мы подробно разберем, почему возникает эта проблема на уровне базы данных, и рассмотрим эффективные программные и интерактивные методы ее решения без необходимости открывать прошлые закрытые периоды.
Давайте выясним техническую причину происходящего. В платформе «1С:Предприятие 8.3» под визуально одинаковым отображением пустого субконто (в виде пустой строки или символов <...>) в таблицах базы данных могут храниться три абсолютно разных значения:
Справочники.Номенклатура.ПустаяСсылка()). Это то значение, которое подставляет система, когда пользователь интерактивно оставляет поле выбора пустым.Когда мы пытаемся сделать ручную операцию вида Дт 94 — Кт 41.01 и выбираем пустое поле в субконто «Номенклатура», программа записывает в проводку именно Пустую ссылку. Если в исходном остатке, который мы хотим списать, фактически записан NULL или Неопределено, то для СУБД это абсолютно разные значения. Из-за этого не происходит уменьшения существующего остатка, а формируется новая проводка с другим типом пустого значения. На экране мы видим две пустые строки, которые не закрывают друг друга.
---
Прежде чем приступать к исправлению, нам необходимо локализовать ошибку и понять, какой документ сформировал некорректную проводку. Для этого сформируем отчет «Карточка субконто» или «Карточка счета» по счету 41.01 за весь период ведения учета, установив отбор по незаполненной номенклатуре.
Если документов-источников немного, а период еще не закрыт для редактирования, самым правильным решением будет зайти в исходный документ и перевыбрать номенклатуру (или склад), после чего перепровести документ. Однако, если период закрыт (например, это данные 2013 года) или таких документов сотни, этот вариант нам не подходит. Нам придется корректировать остатки в текущем открытом периоде.
---
Поскольку интерактивно (в режиме предприятия) пользователь не может выбрать тип значения NULL или Неопределено в ручной операции, единственным надежным способом является написание небольшой внешней обработки. Нам нужно программно прочитать некорректные остатки и создать документ корректировки, перенеся туда аналитику «один в один».
Рассмотрим пример кода, который решает эту задачу. Мы создадим документ ОперацияБух текущей датой и заполним его проводками, которые спишут зависшие остатки на счет 94 (или 91.02).
// Создаем новый документ "Операция, введенная вручную"
НовыйДокумент = Документы.ОперацияБух.СоздатьДокумент();
НовыйДокумент.Дата = ТекущаяДата();
НовыйДокумент.Организация = Справочники.Организации.НайтиПоРеквизиту("ИНН", "7700000000"); // Укажите ИНН организации
НовыйДокумент.Содержание = "Списание остатков с неопределенной аналитикой";
НовыйДокумент.Записать();
// Получаем набор записей регистра бухгалтерии для созданного документа
НаборЗаписей = РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(НовыйДокумент.Ссылка);
// Формируем запрос для получения проблемных остатков по счету 41.01
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ХозрасчетныйОстатки.Субконто1 КАК Номенклатура,
| ХозрасчетныйОстатки.Субконто2 КАК Склад,
| ХозрасчетныйОстатки.Организация КАК Организация,
| ХозрасчетныйОстатки.СуммаОстаток КАК СуммаОстаток,
| ХозрасчетныйОстатки.КоличествоОстаток КАК КоличествоОстаток
|ИЗ
| РегистрБухгалтерии.Хозрасчетный.Остатки(&Период, Счет = &Счет, , ) КАК ХозрасчетныйОстатки
|ГДЕ
| (ХозрасчетныйОстатки.Субконто1 ЕСТЬ NULL
| ИЛИ ХозрасчетныйОстатки.Субконто1 = НЕОПРЕДЕЛЕНО
| ИЛИ ХозрасчетныйОстатки.Субконто1.Ссылка ЕСТЬ NULL)
| ИЛИ (ХозрасчетныйОстатки.Субконто2 ЕСТЬ NULL
| ИЛИ ХозрасчетныйОстатки.Субконто2 = НЕОПРЕДЕЛЕНО)";
Запрос.УстановитьПараметр("Период", Новый Граница(ТекущаяДата(), ВидГраницы.Включая));
Запрос.УстановитьПараметр("Счет", ПланыСчетов.Хозрасчетный.ТоварыНаСкладах); // Счет 41.01
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Заполняем проводку списания Кт 41.01 - Дт 94
Проводка = НаборЗаписей.Добавить();
Проводка.Период = НовыйДокумент.Дата;
Проводка.Организация = Выборка.Организация;
Проводка.Активность = Истина;
// Кредит (списание пустых остатков)
Проводка.СчетКт = ПланыСчетов.Хозрасчетный.ТоварыНаСкладах;
Проводка.СубконтоКт[ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Номенклатура] = Выборка.Номенклатура;
Проводка.СубконтоКт[ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Склады] = Выборка.Склад;
// Заполняем количество по Кредиту, если оно есть
Если Выборка.КоличествоОстаток <> NULL Тогда
Проводка.КоличествоКт = Выборка.КоличествоОстаток;
КонецЕсли;
// Дебет (счет списания расходов)
Проводка.СчетДт = ПланыСчетов.Хозрасчетный.НедостачиИПотериОтПорчиЦенностей; // Счет 94
// Сумма проводки
Проводка.Сумма = Выборка.СуммаОстаток;
КонецЦикла;
// Записываем набор записей в базу данных
Если НаборЗаписей.Количество() > 0 Тогда
НаборЗаписей.Записать();
Сообщить("Успешно сформировано проводки списания в количестве: " + НаборЗаписей.Количество());
Иначе
Сообщить("Проблемных остатков с пустой аналитикой не обнаружено.");
КонецЕсли;
Этот способ гарантирует, что система скопирует из базы данных именно те значения (будь то NULL или Неопределено), которые мешали схлопыванию остатка. После выполнения этого кода зависшие суммы и количества полностью уйдут со счета 41.01.
---
Если мы не хотим использовать внешнюю программную обработку, мы можем воспользоваться универсальным стандартным механизмом платформы. Рассмотрим этот вариант подробнее.
Для этого выполним следующие действия:
41.01, но в поле субконто оставим пустоту. Корреспондирующим счетом по Дебету укажем счет списания (например, 94 или 91.02).Важное примечание: Если в остатках был записан именно физический NULL, ручное заполнение строки в документе корректировки регистров также может выдать раздвоение, так как интерактивно программа подставит пустую ссылку. В таких ситуациях запуск программного скрипта (Шаг 2) остается единственным рабочим решением.
---
Иногда пустое субконто в отчете оказывается так называемой «битой ссылкой». Это происходит, когда объект номенклатуры был физически удален из базы данных (например, внешней обработкой без контроля ссылочной целостности), но движения в регистре по нему остались. В ОСВ это может выглядеть как пустая строка или как длинная строка вида <Объект не найден...>.
Проанализируем, как решить эту проблему через встроенный инструмент тестирования конфигурации:
После завершения процесса тестирования все некорректные «битые» ссылки в проводках превратятся в стандартные Пустые ссылки. После этого мы сможем легко списать эти остатки обычным ручным документом «Операция, введенная вручную», так как типы данных теперь будут полностью совпадать.