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