Как заполнить табличную часть документа Назначение планового начисления на основе данных регистра

Программист 1С v8.3 (Управляемые формы) 1С:Зарплата и Управление Персоналом
← На главную

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

Анализ проблемы: почему запрос выдает ошибки

Рассмотрим ситуацию, с которой столкнулся автор темы. Пытаясь связать данные регистра Расш1_ПрактикаСтудентов и документа НазначениеПлановогоНачисления, разработчик использовал ЛЕВОЕ СОЕДИНЕНИЕ. Однако при выполнении возникла ошибка "Ожидается имя таблицы". Выясним причину: в языке запросов 1С после конструкции ЛЕВОЕ СОЕДИНЕНИЕ обязательно должно следовать ключевое слово ПО, описывающее условие связи таблиц.

Проанализируем пример некорректного кода:


ЛЕВОЕ СОЕДИНЕНИЕ Документ.НазначениеПлановогоНачисления КАК НазначениеПлановогоНачисления
ГДЕ Расш1_ПрактикаСтудентовДанныеПоПрактике.Ссылка.ДатаНачала >= НазначениеПлановогоНачисления.ДатаНазначения

В данном случае условие фильтрации ошибочно помещено в секцию ГДЕ, тогда как для соединения таблиц необходимо четко указать поля связи. Но даже после исправления синтаксиса на ПО Регистратор = Ссылка, данные могут не выбираться. Почему так происходит? Ответ прост: если документ еще не записан в базу данных, запрос к таблице Документ.НазначениеПлановогоНачисления просто не найдет текущий объект, так как его еще нет в физических таблицах СУБД.

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

Для заполнения табличной части документа из формы (обработки) самым правильным и производительным способом является передача дат документа в запрос через параметры. Это избавляет от необходимости соединять таблицы и позволяет работать даже с еще не сохраненными данными.

Рассмотрим по шагам, как реализовать этот алгоритм:

  1. Получаем данные из объекта: Мы берем значения реквизитов ДатаНазначения и ДатаОкончания напрямую из данных формы (объекта).
  2. Устанавливаем параметры: Передаем эти значения в запрос.
  3. Формируем условие в запросе: Используем оператор МЕЖДУ или сравнение дат.

Разберем пример реализации процедуры на сервере:


Процедура Расш1_ЗаполнитьРуководителямиПрактикНаСервере()
    
    // Очищаем текущую табличную часть перед заполнением
    Объект.Сотрудники.Очистить();
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	Практика.ДатаНачала КАК ДатаНачала,
        |	Практика.ДатаОкончания КАК ДатаОкончания,
        |	Практика.НазначаемыйРуководитель КАК Руководитель
        |ИЗ
        |	РегистрСведений.Расш1_ПрактикаСтудентов КАК Практика
        |ГДЕ
        |	Практика.ДатаНачала МЕЖДУ &НачалоДокумента И &КонецДокумента";
    
    // Устанавливаем параметры из реквизитов текущего документа
    Запрос.УстановитьПараметр("НачалоДокумента", Объект.ДатаНазначения);
    
    // Обработка пустой даты окончания (если начисление бессрочное)
    Если ЗначениеЗаполнено(Объект.ДатаОкончания) Тогда
        Запрос.УстановитьПараметр("КонецДокумента", Объект.ДатаОкончания);
    Иначе
        // Если дата не задана, используем максимально возможное значение
        Запрос.УстановитьПараметр("КонецДокумента", Дата('39991231'));
    КонецЕсли;

    Выборка = Запрос.Выполнить().Выбрать();

    Пока Выборка.Следующий() Цикл
        НоваяСтрока = Объект.Сотрудники.Добавить();
        НоваяСтрока.Сотрудник = Выборка.Руководитель;
        НоваяСтрока.ДатаНазначения = Выборка.ДатаНачала;
        НоваяСтрока.ДатаОкончания = Выборка.ДатаОкончания;
    КонецЦикла;

КонецПроцедуры

Нюансы логики пересечения периодов

Часто условия МЕЖДУ недостаточно. Рассмотрим ситуацию: практика студента началась раньше, чем дата назначения начисления, но продолжается в течение этого периода. В этом случае ДатаНачала практики не попадет в интервал документа, и запись будет пропущена.

Проанализируем универсальную формулу пересечения периодов. Чтобы найти все записи, которые хотя бы частично "наслаиваются" на период документа, нужно использовать следующее условие в секции ГДЕ:


ГДЕ
    Практика.ДатаНачала <= &КонецДокумента
    И (Практика.ДатаОкончания >= &НачалоДокумента ИЛИ Практика.ДатаОкончания = ДАТАВРЕМЯ(1, 1, 1))

Такой подход гарантирует, что вы подберете всех релевантных сотрудников, независимо от того, совпадает ли их начало работы с датой документа или началось задолго до него. Особенно это актуально для документа НазначениеПлановогоНачисления, так как начисления могут назначаться в середине уже идущего процесса практики.

Особенности работы с типовой конфигурацией (ЗУП 3.1)

Документ НазначениеПлановогоНачисления является частью сложного кадрового механизма. Простого добавления строк в табличную часть Сотрудники может быть недостаточно для корректного расчета. Рассмотрим важные моменты:

  1. Заполнение связанных реквизитов: В типовых решениях при добавлении сотрудника должны заполняться скрытые идентификаторы строк и показатели. После программного добавления рекомендуется вызвать стандартные обработчики, если они доступны в модуле формы.
  2. Контекст сервера: Все манипуляции с запросами и табличными частями должны происходить строго в серверном контексте. При вызове из команды формы убедитесь, что используется &НаСервере.
  3. Проверка прав: Если вы используете данные из расширения (как в нашем примере Расш1_...), убедитесь, что у пользователя, запускающего заполнение, есть права на чтение этого регистра. В противном случае запрос вернет пустой результат без сообщений об ошибках.
  4. Использование СрезаПоследних: Если ваш регистр сведений является периодическим, вместо обращения к основной таблице РегистрСведений.Расш1_ПрактикаСтудентов, рассмотрите использование виртуальной таблицы СрезПоследних. Это позволит получить актуального руководителя на конкретную дату, избегая дублирования строк при многократных изменениях в регистре.

Итоги

Мы выяснили, что основной причиной неудач при заполнении табличных частей является попытка использовать ЛЕВОЕ СОЕДИНЕНИЕ с таблицей самого документа. Переход к использованию параметров (&НачалоДокумента, &КонецДокумента) делает код чище, быстрее и позволяет работать с новыми (незаписанными) объектами. Применяйте описанные методики пересечения периодов и не забывайте об очистке табличной части перед повторным заполнением, чтобы избежать дублей данных.

← На главную