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