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