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