Как создать отчет по начислениям сотрудников с отбором по уволенным и избежать типовых ошибок в 1С?

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

При создании отчетов в системе 1С:Предприятие часто возникает необходимость объединения данных из различных источников, таких как регистры сведений, справочники, документы. В частности, задача формирования отчета по начислениям сотрудников, который бы корректно обрабатывал уволенных работников и включал их кадровые данные, является достаточно распространенной. Рассмотрим подробно, как эффективно решить эту задачу, избегая распространенных ошибок, таких как пропуск сотрудников или показателей, а также несоответствие типов данных.

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

Изначально, вы можете столкнуться с проблемой, пытаясь использовать стандартный "Универсальный отчет" для решения этой задачи. Важно понимать, что "Универсальный отчет" обычно предназначен для работы с одним источником данных (одной таблицей, регистром, справочником). Если нам требуется объединить данные из нескольких таблиц, настроить сложные отборы или группировки, "Универсальный отчет" не сможет предоставить необходимую гибкость. В таких случаях нам потребуется создать собственный отчет, используя Систему компоновки данных (СКД) или напрямую написать запрос.

Первым шагом нам нужно получить информацию о дате увольнения сотрудников. В системе 1С:Зарплата и Управление Персоналом (ЗУП) или аналогичных конфигурациях для этого используются следующие регистры сведений:

  1. РегистрСведений.ТекущиеКадровыеДанныеСотрудников: Этот регистр содержит актуальные кадровые данные по сотрудникам на текущий момент, включая дату увольнения, если сотрудник уволен. Он удобен для получения "среза последних" данных.
  2. РегистрСведений.КадроваяИсторияСотрудников: Этот регистр хранит историю всех кадровых событий (прием, перевод, увольнение). Если нам нужна полная история или специфические события, обращаемся к нему, часто используя срез последних по определенному виду события или по периоду.

Предположим, наш основной источник данных — это РегистрСведений.ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников.СрезПоследних. Мы хотим добавить к нему дату увольнения. Для этого нам необходимо соединить (связать) эти таблицы в запросе.

Выбираем правильный тип соединения: ВНУТРЕННЕЕ или ЛЕВОЕ СОЕДИНЕНИЕ

Критически важно выбрать правильный тип соединения таблиц:

  1. ВНУТРЕННЕЕ СОЕДИНЕНИЕ (INNER JOIN): При использовании внутреннего соединения в результат запроса попадут только те записи, для которых есть соответствие в обеих соединяемых таблицах по указанным полям. Это может привести к потере данных, если, например, для какого-то сотрудника нет записи в регистре кадровых данных, или, наоборот, нет записей о показателях, но есть кадровые данные.
  2. ЛЕВОЕ СОЕДИНЕНИЕ (LEFT JOIN): Левое соединение возвращает все записи из "левой" таблицы (той, что указана первой в операторе ИЗ) и совпадающие записи из "правой" таблицы. Если совпадений в "правой" таблице нет, поля из нее будут содержать значение NULL. Этот тип соединения предпочтителен, когда мы хотим сохранить все записи из основного источника данных, даже если для них нет связанных данных в другой таблице.

В нашем случае, если основной источник данных — ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников.СрезПоследних, и мы хотим видеть всех сотрудников с их показателями, даже если они еще не уволены (и, соответственно, не имеют даты увольнения в регистре), или если по какой-то причине отсутствует запись в регистре кадровых данных, нам следует использовать ЛЕВОЕ СОЕДИНЕНИЕ.

Рассмотрим пример запроса, который объединяет значения периодических показателей с текущими кадровыми данными, используя ЛЕВОЕ СОЕДИНЕНИЕ, чтобы избежать потери сотрудников:


ВЫБРАТЬ РАЗРЕШЕННЫЕ
    ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Период КАК Период,
    ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Сотрудник КАК Сотрудник,
    ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Организация КАК Организация,
    ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.ФизическоеЛицо КАК ФизическоеЛицо,
    ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Показатель КАК Показатель,
    ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Значение КАК Значение,
    ТекущиеКадровыеДанныеСотрудников.ДатаУвольнения КАК ДатаУвольнения
ИЗ
    РегистрСведений.ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников.СрезПоследних({(&КонецПериода)}) КАК ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ТекущиеКадровыеДанныеСотрудников КАК ТекущиеКадровыеДанныеСотрудников
        ПО ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Сотрудник = ТекущиеКадровыеДанныеСотрудников.Сотрудник
        И ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Организация = ТекущиеКадровыеДанныеСотрудников.ГоловнаяОрганизация
        И ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.ФизическоеЛицо = ТекущиеКадровыеДанныеСотрудников.ФизическоеЛицо

Обратите внимание на условия соединения: мы связываем таблицы по полям Сотрудник, Организация (важно учитывать, что в ТекущиеКадровыеДанныеСотрудников это поле называется ГоловнаяОрганизация) и ФизическоеЛицо. Это обеспечивает точное соответствие записей.

Добавляем отбор по уволенным сотрудникам

После того как мы объединили данные, мы можем добавить отбор. Чтобы исключить уволенных сотрудников, мы используем поле ДатаУвольнения, которое теперь доступно в нашем запросе благодаря соединению. Если сотрудник не уволен, то поле ДатаУвольнения будет иметь значение NULL.

Для того чтобы в отчете остались только работающие сотрудники, мы можем добавить условие в секцию ГДЕ или в параметры отчета СКД:


ГДЕ
    ТекущиеКадровыеДанныеСотрудников.ДатаУвольнения ЕСТЬ NULL

Если же, наоборот, нам нужны только уволенные сотрудники, условие будет выглядеть так:


ГДЕ
    ТекущиеКадровыеДанныеСотрудников.ДатаУвольнения ЕСТЬ НЕ NULL

Или, для конкретного периода увольнения:


ГДЕ
    ТекущиеКадровыеДанныеСотрудников.ДатаУвольнения МЕЖДУ &НачалоПериодаУвольнения И &КонецПериодаУвольнения

Разбираемся с пропавшими сотрудниками и показателями

Проблема, когда в отчете отсутствуют некоторые сотрудники или их показатели (например, Компенсация расходов при дистанционной работе или Премия индивидуальная ежемесячная), является одной из самых частых при построении сложных отчетов. Рассмотрим основные причины и способы их устранения.

Почему пропадают сотрудники при ВНУТРЕННЕЕ СОЕДИНЕНИЕ?

Как мы уже выяснили, ВНУТРЕННЕЕ СОЕДИНЕНИЕ требует наличия соответствия в обеих таблицах. Если вы использовали ВНУТРЕННЕЕ СОЕДИНЕНИЕ, как в запросе из сообщения 17:


ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ТекущиеКадровыеДанныеСотрудников КАК ТекущиеКадровыеДанныеСотрудников
ПО ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Сотрудник = ТекущиеКадровыеДанныеСотрудников.Сотрудник
И ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Организация = ТекущиеКадровыеДанныеСотрудников.ГоловнаяОрганизация
И ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.ФизическоеЛицо = ТекущиеКадровыеДанныеСотрудников.ФизическоеЛицо

...то причиной пропажи сотрудников является, скорее всего, отсутствие соответствующей записи в регистре ТекущиеКадровыеДанныеСотрудников по всем указанным условиям соединения для этих трех работников. Возможно, для них нет актуальных кадровых данных на указанную дату среза, или есть какие-то несоответствия в полях Организация/ГоловнаяОрганизация, ФизическоеЛицо. Использование ЛЕВОГО СОЕДИНЕНИЯ, как показано в предыдущем примере, является решением для включения всех сотрудников из основного источника.

Почему отсутствуют показатели начислений?

Если у сотрудника не попадают определенные показатели (например, Компенсация расходов при дистанционной работе или Премия индивидуальная ежемесячная), даже если назначение планового начисления по ним есть, необходимо провести комплексную проверку. Разберем по шагам, что следует проанализировать:

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

Тщательная проверка этих пунктов позволит выявить причину отсутствия показателей.

Устраняем ошибку "Несоответствие типов" и оптимизируем запрос

Ошибка "Несоответствие типов" (или "Несоотвествие типов", как указано в сообщении 19) является одной из самых распространенных при работе с запросами в 1С. Она возникает, когда вы пытаетесь выполнить операцию (сравнение, присвоение, использование в функции) со значениями, которые имеют несовместимые типы данных (например, сравниваете число с датой, или ссылку на объект с пустой ссылкой).

Типичные причины ошибки "Несоответствие типов":

  1. Неправильные условия соединения: Это наиболее частая причина. Например, попытка соединить Справочник.Сотрудники.Ссылка (тип Ссылка) с полем типа Строка или Число. Или соединение по полю Организация, когда в одной таблице это ссылка, а в другой – строка или NULL.
  2. Передача неверного типа параметра: Если в запросе используется параметр (например, {(&КонецПериода)}), и вы передаете в него значение, тип которого не соответствует ожидаемому (например, строку вместо даты).
  3. Использование функций с неподходящими аргументами: Попытка применить функцию для работы с датами к числовому полю, или функцию для строк к ссылочному полю.

Рассмотрим запрос из сообщения 18, который вызвал ошибку "Несоответствие типов":


ВЫБРАТЬ РАЗРЕШЕННЫЕ
    Сотрудники.Ссылка КАК Сотрудник,
    КадроваяИсторияСотрудниковСрезПоследних.Организация КАК Организация,
    КадроваяИсторияСотрудниковСрезПоследних.Подразделение КАК Подразделение,
    КадроваяИсторияСотрудниковСрезПоследних.Должность КАК Должность,
    ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Показатель КАК Показатель,
    ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Значение КАК Значение,
    ТекущиеКадровыеДанныеСотрудников.ДатаУвольнения КАК ДатаУвольнения
ИЗ
    РегистрСведений.КадроваяИсторияСотрудников.СрезПоследних КАК КадроваяИсторияСотрудниковСрезПоследних
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Сотрудники КАК Сотрудники
        ПРАВОЕ СОЕДИНЕНИЕ РегистрСведений.ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников.СрезПоследних КАК ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних
        ПО (ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Сотрудник = Сотрудники.Ссылка)
        ПРАВОЕ СОЕДИНЕНИЕ РегистрСведений.ТекущиеКадровыеДанныеСотрудников КАК ТекущиеКадровыеДанныеСотрудников
        ПО (ТекущиеКадровыеДанныеСотрудников.Сотрудник = Сотрудники.Ссылка)
        ПО КадроваяИсторияСотрудниковСрезПоследних.Сотрудник = Сотрудники.Ссылка И КадроваяИсторияСотрудниковСрезПоследних.ГоловнойСотрудник = Сотрудники.Ссылка

В этом запросе есть несколько потенциальных проблем:

  1. Смешанное использование ЛЕВОЕ и ПРАВОЕ СОЕДИНЕНИЕ: Смешивание ЛЕВОЕ и ПРАВОЕ СОЕДИНЕНИЕ может быть очень запутанным и приводить к неожиданным результатам, а также к ошибкам типов, если порядок выполнения соединений не тот, который вы предполагаете. Лучше всего придерживаться одной стратегии, например, всегда использовать ЛЕВОЕ СОЕДИНЕНИЕ, начиная с основной (самой полной) таблицы.
  2. Некорректная цепочка ПО: Обратите внимание на последнюю строку с ПО КадроваяИсторияСотрудниковСрезПоследних.Сотрудник = Сотрудники.Ссылка И КадроваяИсторияСотрудниковСрезПоследних.ГоловнойСотрудник = Сотрудники.Ссылка. Она относится к РегистрСведений.КадроваяИсторияСотрудников.СрезПоследних. Однако, если Справочник.Сотрудники был "левой" таблицей для КадроваяИсторияСотрудниковСрезПоследних, а затем к Справочник.Сотрудники присоединялись другие таблицы через ПРАВОЕ СОЕДИНЕНИЕ, связь может быть потеряна или некорректно установлена, вызывая ошибку типа.
  3. Соединение по Сотрудники.Ссылка: Само по себе это правильно, если Сотрудник в регистрах является ссылкой на справочник Сотрудники. Но важно, чтобы это всегда было так.

Оптимизированный и унифицированный запрос

Давайте построим более надежный запрос, используя ЛЕВОЕ СОЕДИНЕНИЕ от основного регистра с показателями, чтобы получить всех сотрудников и их данные, даже если некоторые данные отсутствуют:


ВЫБРАТЬ РАЗРЕШЕННЫЕ
    ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Период КАК ПериодПоказателя,
    ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Сотрудник КАК Сотрудник,
    ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Организация КАК ОрганизацияПоказателя,
    ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Показатель КАК Показатель,
    ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Значение КАК ЗначениеПоказателя,
    ТекущиеКадровыеДанныеСотрудников.ДатаУвольнения КАК ДатаУвольнения,
    Сотрудники.Наименование КАК НаименованиеСотрудника,
    Сотрудники.Подразделение КАК ПодразделениеСотрудника,
    Сотрудники.Должность КАК ДолжностьСотрудника,
    КадроваяИсторияСотрудниковСрезПоследних.ВидСобытияКадровойИстории КАК ВидКадровогоСобытия
ИЗ
    РегистрСведений.ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников.СрезПоследних({(&КонецПериода)}) КАК ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних

    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Сотрудники КАК Сотрудники
    ПО ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Сотрудник = Сотрудники.Ссылка

    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ТекущиеКадровыеДанныеСотрудников КАК ТекущиеКадровыеДанныеСотрудников
    ПО ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Сотрудник = ТекущиеКадровыеДанныеСотрудников.Сотрудник
    И ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Организация = ТекущиеКадровыеДанныеСотрудников.ГоловнаяОрганизация
    И ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.ФизическоеЛицо = ТекущиеКадровыеДанныеСотрудников.ФизическоеЛицо

    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КадроваяИсторияСотрудников.СрезПоследних(
        {(&КонецПериода)},
        Сотрудник = ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Сотрудник
        И Организация = ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Организация
    ) КАК КадроваяИсторияСотрудниковСрезПоследних
    ПО ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Сотрудник = КадроваяИсторияСотрудниковСрезПоследних.Сотрудник
    И ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Организация = КадроваяИсторияСотрудниковСрезПоследних.Организация

ГДЕ
    // Пример отбора: только работающие сотрудники (не уволенные)
    ТекущиеКадровыеДанныеСотрудников.ДатаУвольнения ЕСТЬ NULL
    // Или другой отбор, если нужен. Например, только сотрудники с определенным показателем:
    // И ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Показатель = &ВыбранныйПоказатель

В этом запросе мы сделали следующее:

  1. Начали с основного источника данных ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников.СрезПоследних, что гарантирует наличие всех показателей, которые нас интересуют.
  2. Последовательно присоединили Справочник.Сотрудники для получения общих данных о сотруднике (Наименование, Подразделение, Должность).
  3. Затем присоединили РегистрСведений.ТекущиеКадровыеДанныеСотрудников для получения ДатаУвольнения, используя ЛЕВОЕ СОЕДИНЕНИЕ и подробные условия связи по Сотрудник, Организация (ГоловнаяОрганизация), ФизическоеЛицо. Это максимально снижает риск ошибки "Несоответствие типов", так как мы точно связываем поля одинакового типа.
  4. (Опционально) Присоединили РегистрСведений.КадроваяИсторияСотрудников.СрезПоследних для получения информации о последних кадровых событиях. Здесь важно правильно использовать параметры среза для этого регистра.
  5. Добавили секцию ГДЕ для отбора по уволенным/работающим сотрудникам, используя поле ДатаУвольнения из присоединенного регистра.

Такой подход обеспечивает максимальную надежность запроса и минимизирует вероятность ошибок "Несоответствие типов" или пропажи данных.

Для отладки запросов и проверки их работоспособности всегда используйте Консоль запросов. Она позволяет пошагово выполнять запрос, просматривать промежуточные результаты и оперативно выявлять ошибки.

Итоги и рекомендации

Создание отчета по начислениям с учетом кадровых данных требует внимательного подхода к формированию запросов. Всегда начинайте с определения основного источника данных, а затем постепенно присоединяйте необходимые вспомогательные регистры и справочники, используя ЛЕВОЕ СОЕДИНЕНИЕ, чтобы сохранить максимальное количество данных из основного источника.

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

Если возникают ошибки "Несоответствие типов", тщательно проверяйте типы данных во всех полях, участвующих в условиях соединения и отбора. Пропажа данных чаще всего связана с неправильным типом соединения (использование ВНУТРЕННЕГО вместо ЛЕВОГО) или некорректными параметрами срезов. Последовательная отладка в Консоли запросов поможет быстро выявить и устранить проблему.

← На главную