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