При работе с 1С 7.7 и использовании внешних компонент для выполнения прямых SQL-запросов (например, 1С++), разработчики часто сталкиваются с ситуацией, когда данные в отчете не сходятся с тем, что показывает стандартный просмотрщик движений регистров. Типичный пример: сумма поступления в запросе составляет 6000 рублей, а в регистре мы видим 6100 рублей. Рассмотрим подробнее, почему возникают такие расхождения и как правильно составить запрос, чтобы учесть все составляющие себестоимости, включая дополнительные расходы.
Разберем ситуацию: у нас есть документ ПоступлениеТМЦ_Склад, на основании которого введен документ Поступление_ДопРасходы. В визуальном интерфейсе 1С мы видим итоговую сумму по партии, которая включает и стоимость товара, и логистические затраты. Однако прямой запрос к таблице регистра ПартииНаличие (таблица RA) выдает только "чистую" сумму закупки.
Основная причина заключается в архитектуре хранения движений в 1С 7.7. Каждый документ делает свои собственные записи в таблицу движений регистра. Просмотрщик регистров в конфигураторе или в режиме предприятия суммирует все записи по определенному набору измерений (Номенклатура, Партия и т.д.). В то же время, если в SQL-запросе мы устанавливаем фильтр по конкретному виду документа (например, через iddocdef), мы сознательно отсекаем записи, созданные другими документами, даже если они относятся к той же самой партии товара.
Проанализируем механику записи дополнительных расходов:
Количество = 10, Сумма = 1000.Количество = 0, Сумма = 100.Если наш запрос ищет только движения документа вида "Поступление", он найдет только первую запись. Сумма в 100 рублей будет проигнорирована, так как она привязана к IDDoc другого документа.
Посмотрим на фрагмент кода, который часто приводит к ошибке:
WHERE
ЖурналДок.iddocdef = $ВидДокумента.ПоступлениеТМЦ_Склад AND
$Рег.Номенклатура IN (SELECT val FROM #TempTable)
Здесь мы явно ограничиваем выборку только одним типом документа. Выясним, как это исправить. Вместо того чтобы привязываться к конкретному первичному документу, необходимо ориентироваться на аналитику учета — Партию. Именно объект Справочник.Партии является ключом, объединяющим все затраты на конкретное поступление товара.
Рассмотрим правильный подход. Чтобы получить полную стоимость последнего прихода, нам нужно сначала определить ID последней партии для каждой номенклатуры, а затем просуммировать все движения по этой партии в регистре, не ограничивая себя типом документа.
Пример логики запроса:
Партия.SUM($Рег.СуммаРуб) по всем записям регистра, где $Рег.Партия = :НайденнаяПартия.Если бизнес-логика требует жесткого контроля типов документов (например, нужно разделять основную стоимость и доп. расходы в разные колонки), можно воспользоваться объединением запросов. Посмотрим на пример структуры такого запроса:
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.
Например, разные документы (Поступление ТМЦ, Поступление ТМЦ (импорт), Поступление из переработки) могут делать движения с одним и тем же смысловым кодом операции. Настроив фильтр по коду операции, мы получим более универсальный код, который не сломается при добавлении в систему новых видов документов закупки.
При выполнении прямых запросов к $Регистр.ПартииНаличие следует помнить о следующих моментах:
$РегистрОстатки или $РегистрОбороты). Они автоматически суммируют все движения и работают значительно быстрее, чем ручное обращение к физической таблице RA.Для того чтобы данные в запросе совпадали с "Просмотром движений", мы должны отказаться от фильтрации по конкретному IDDoc или iddocdef в тех случаях, когда рассчитывается стоимостный показатель партии. Нужно суммировать все записи регистра, относящиеся к выбранному объекту из справочника Партии. Только такой подход гарантирует включение всех корректировок, возвратов и дополнительных затрат в итоговую себестоимость.