Почему не совпадают значения сумм в прямом запросе и просмотрщике регистров в 1С 7.7

Программист 1С v7.7 Управленческий учет Торговля и дистрибуция
← На главную

При работе с 1С 7.7 и использовании внешних компонент для выполнения прямых SQL-запросов (например, 1С++), разработчики часто сталкиваются с ситуацией, когда данные в отчете не сходятся с тем, что показывает стандартный просмотрщик движений регистров. Типичный пример: сумма поступления в запросе составляет 6000 рублей, а в регистре мы видим 6100 рублей. Рассмотрим подробнее, почему возникают такие расхождения и как правильно составить запрос, чтобы учесть все составляющие себестоимости, включая дополнительные расходы.

Анализ причины расхождения данных

Разберем ситуацию: у нас есть документ ПоступлениеТМЦ_Склад, на основании которого введен документ Поступление_ДопРасходы. В визуальном интерфейсе 1С мы видим итоговую сумму по партии, которая включает и стоимость товара, и логистические затраты. Однако прямой запрос к таблице регистра ПартииНаличие (таблица RA) выдает только "чистую" сумму закупки.

Основная причина заключается в архитектуре хранения движений в 1С 7.7. Каждый документ делает свои собственные записи в таблицу движений регистра. Просмотрщик регистров в конфигураторе или в режиме предприятия суммирует все записи по определенному набору измерений (Номенклатура, Партия и т.д.). В то же время, если в SQL-запросе мы устанавливаем фильтр по конкретному виду документа (например, через iddocdef), мы сознательно отсекаем записи, созданные другими документами, даже если они относятся к той же самой партии товара.

Проанализируем механику записи дополнительных расходов:

  1. Документ Поступление ТМЦ создает запись в регистре: Количество = 10, Сумма = 1000.
  2. Документ Доп. расходы создает отдельную запись по той же самой партии: Количество = 0, Сумма = 100.

Если наш запрос ищет только движения документа вида "Поступление", он найдет только первую запись. Сумма в 100 рублей будет проигнорирована, так как она привязана к IDDoc другого документа.

Проблема фильтрации по виду документа

Посмотрим на фрагмент кода, который часто приводит к ошибке:


WHERE
    ЖурналДок.iddocdef = $ВидДокумента.ПоступлениеТМЦ_Склад AND    
    $Рег.Номенклатура IN (SELECT val FROM #TempTable)

Здесь мы явно ограничиваем выборку только одним типом документа. Выясним, как это исправить. Вместо того чтобы привязываться к конкретному первичному документу, необходимо ориентироваться на аналитику учета — Партию. Именно объект Справочник.Партии является ключом, объединяющим все затраты на конкретное поступление товара.

Вариант решения №1: Группировка по партии без привязки к документу

Рассмотрим правильный подход. Чтобы получить полную стоимость последнего прихода, нам нужно сначала определить ID последней партии для каждой номенклатуры, а затем просуммировать все движения по этой партии в регистре, не ограничивая себя типом документа.

Пример логики запроса:

  1. Находим максимальную дату/время (или максимальный IDDoc) поступления для номенклатуры.
  2. Получаем из этой записи значение измерения Партия.
  3. Делаем SUM($Рег.СуммаРуб) по всем записям регистра, где $Рег.Партия = :НайденнаяПартия.

Вариант решения №2: Использование UNION ALL для объединения разных типов документов

Если бизнес-логика требует жесткого контроля типов документов (например, нужно разделять основную стоимость и доп. расходы в разные колонки), можно воспользоваться объединением запросов. Посмотрим на пример структуры такого запроса:


SELECT 
    sub.Номенклатура,
    SUM(sub.СуммаОсн) as ОсновнаяСумма,
    SUM(sub.СуммаДоп) as ДопРасходы
FROM (
    /* Выбираем основные поступления */
    SELECT 
        $Рег.Номенклатура as Номенклатура,
        $Рег.СуммаРуб as СуммаОсн,
        0 as СуммаДоп
    FROM $Регистр.ПартииНаличие as Рег
    INNER JOIN _1Sjourn as Журнал ON Журнал.IDDoc = Рег.IDDoc
    WHERE Журнал.iddocdef = $ВидДокумента.ПоступлениеТМЦ_Склад

    UNION ALL

    /* Выбираем доп. расходы */
    SELECT 
        $Рег.Номенклатура,
        0,
        $Рег.СуммаРуб
    FROM $Регистр.ПартииНаличие as Рег
    INNER JOIN _1Sjourn as Журнал ON Журнал.IDDoc = Рег.IDDoc
    WHERE Журнал.iddocdef = $ВидДокумента.Поступление_ДопРасходы
) sub
GROUP BY sub.Номенклатура

Использование Кода Операции для точности

Проанализируем еще один важный аспект. В типовых конфигурациях 1С 7.7 в регистрах часто присутствует реквизит КодОперации. Использование этого поля гораздо надежнее, чем фильтрация по iddocdef.

Например, разные документы (Поступление ТМЦ, Поступление ТМЦ (импорт), Поступление из переработки) могут делать движения с одним и тем же смысловым кодом операции. Настроив фильтр по коду операции, мы получим более универсальный код, который не сломается при добавлении в систему новых видов документов закупки.

Рекомендации по оптимизации производительности

При выполнении прямых запросов к $Регистр.ПартииНаличие следует помнить о следующих моментах:

Итоговый вывод

Для того чтобы данные в запросе совпадали с "Просмотром движений", мы должны отказаться от фильтрации по конкретному IDDoc или iddocdef в тех случаях, когда рассчитывается стоимостный показатель партии. Нужно суммировать все записи регистра, относящиеся к выбранному объекту из справочника Партии. Только такой подход гарантирует включение всех корректировок, возвратов и дополнительных затрат в итоговую себестоимость.

← На главную