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