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