Как запретить проведение документа «Прием на работу» с уже оформленным сотрудником?

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

При работе с системой 1С часто возникает необходимость контролировать уникальность данных, особенно в кадровых документах. Один из типичных сценариев — это предотвращение повторного приема на работу сотрудника, который уже числится в базе данных как оформленный по другому проведенному документу «Прием на работу». Представим ситуацию: у вас есть документ «Прием на работу» с табличной частью, которая позволяет оформить одного сотрудника сразу на несколько вакансий. Наша задача заключается в том, чтобы не допустить создание и проведение нового документа, если в нем указан сотрудник, который уже фигурирует в другом, ранее проведенном документе того же типа.

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

Выбор места для реализации проверки: процедура ОбработкаПроведения

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

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

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

Размещение кода проверки в ОбработкаПроведения гарантирует, что она будет выполняться единообразно вне зависимости от того, как именно происходит проведение – интерактивно пользователем или программно. Это обеспечивает надежность нашего механизма контроля.

Пошаговый алгоритм запрета проведения документа

Теперь давайте представим подробный алгоритм, который мы будем использовать для контроля уникальности сотрудников в документе «Прием на работу». Этот алгоритм обеспечит, что каждый сотрудник будет оформлен только один раз через документ такого типа.

  1. Перебор сотрудников в табличной части текущего документа.

    Наш документ «Прием на работу» может иметь табличную часть, которая позволяет оформлять нескольких сотрудников или одного сотрудника на несколько вакансий. В любом случае, нам необходимо проверить каждого сотрудника, указанного в текущем документе. Мы будем итерироваться по каждой строке табличной части документа, извлекая из нее реквизит Сотрудник. Это позволит нам последовательно анализировать каждого кандидата на прием.

  2. Формирование и выполнение запроса к базе данных.

    Для каждого сотрудника, полученного на предыдущем шаге, нам необходимо выполнить запрос к базе данных 1С. Цель этого запроса — найти все другие проведенные документы «Прием на работу», в табличных частях которых фигурирует данный сотрудник. Давайте разберем, как мы будем строить такой запрос:

    • Обращение к табличной части документа: В запросе мы должны будем обращаться непосредственно к табличной части документа как к отдельной таблице. Для нашего документа «Прием на работу» и его табличной части, например, ТабличнаяЧастьСотрудники, путь в запросе будет выглядеть как Документ.ПриемНаРаботу.ТабличнаяЧастьСотрудники. Это позволяет нам получить доступ к данным, хранящимся в строках табличной части.
    • Условие по сотруднику: Главное условие нашего запроса — это поиск строк, где реквизит Сотрудник равен сотруднику, которого мы сейчас проверяем. Для этого мы используем параметр запроса: ДокументПриемНаРаботуСотрудники.Сотрудник = &Сотрудник. Это гарантирует, что мы ищем конкретного человека.
    • Исключение текущего документа: Если мы перепроводим документ, нам не нужно, чтобы он сам себе запрещал проведение. Поэтому мы должны добавить условие, которое исключает ссылку на текущий документ из результатов поиска: ДокументПриемНаРаботуСотрудники.Ссылка <> &ТекущийДокумент. Параметр &ТекущийДокумент будет содержать ссылку на документ, который сейчас находится в процессе проведения.
    • Проверка на проведенность: Критически важно учитывать только *проведенные* документы. Непроведенные или помеченные на удаление документы не должны влиять на нашу проверку. Поэтому мы добавляем условие ДокументПриемНаРаботуСотрудники.Ссылка.Проведен = ИСТИНА. Это гарантирует, что мы проверяем только активные и действующие записи о приеме на работу.
    • Оптимизация запроса: Мы используем конструкцию ВЫБРАТЬ ПЕРВЫЕ 1. Это оптимизация, которая позволяет запросу прекратить поиск сразу после нахождения первой же записи, удовлетворяющей условиям. Нам не нужно знать все дублирующиеся документы, достаточно факта наличия хотя бы одного.

    После формирования запроса мы устанавливаем его параметры (&Сотрудник и &ТекущийДокумент) и выполняем его.

  3. Анализ результатов запроса и принятие решения.

    Получив результат выполнения запроса, мы анализируем его. Если запрос вернул хотя бы одну запись (то есть, результат запроса не пустой), это означает, что сотрудник, которого мы пытаемся оформить, уже числится в другом проведенном документе «Прием на работу». В этом случае мы должны запретить проведение текущего документа. Мы делаем это, устанавливая параметр Отказ = Истина и выводим пользователю информативное сообщение, которое четко объясняет причину отказа в проведении. После этого мы прерываем дальнейшее выполнение процедуры с помощью оператора Возврат, так как дальнейшие проверки или обработка уже не имеют смысла.

Пример реализации проверки на 1С (псевдокод)

Теперь, когда мы детально разобрали алгоритм, давайте посмотрим, как он может быть реализован в коде 1С. Представленный ниже псевдокод демонстрирует структуру и основные элементы, которые необходимо использовать в процедуре ОбработкаПроведения модуля объекта документа «Прием на работу».


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

        // Выполняем запрос
        РезультатЗапроса = Запрос.Выполнить();
        
        // Проверяем, вернул ли запрос какие-либо записи
        // Если РезультатЗапроса.Пустой() = Ложь (то есть, не пустой), значит, дубликат найден
        Если НЕ РезультатЗапроса.Пустой() Тогда
            // Если дубликат найден, выводим пользователю сообщение об ошибке
            Сообщить("Сотрудник " + СтрокаТЧ.Сотрудник + " уже оформлен другим проведенным документом ""Прием на работу"". Проведение документа отменено.");
            
            // Устанавливаем параметр Отказ в Истина, чтобы запретить проведение документа
            Отказ = Истина;
            
            // Выходим из процедуры, так как уже найдено дублирование, и нет смысла проверять других сотрудников
            Возврат; 
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Давайте поясним некоторые детали этого кода:

Дополнительные рекомендации и важные нюансы

Помимо основного алгоритма, существуют дополнительные аспекты, которые следует учесть для создания более надежного, гибкого и производительного решения.

  1. Учет различных статусов сотрудника.

    Наш текущий алгоритм строго запрещает проведение, если сотрудник уже есть в *любом* проведенном документе «Прием на работу». Однако бизнес-логика может быть сложнее. Что, если сотрудник был уволен, а теперь снова принимается на работу? В таком случае, простое наличие предыдущего документа «Прием на работу» не должно быть препятствием.

    Для таких сценариев нам потребуется более сложная логика запроса. Вместо простого поиска по документу «Прием на работу» мы можем обратиться к регистрам сведений, которые хранят актуальные данные о занятости сотрудника (например, «СостояниеСотрудниковОрганизаций» или аналогичные в типовых конфигурациях ЗУП). Запрос должен будет проверять не просто факт приема, а текущий статус сотрудника на определенную дату (например, на дату документа «Прием на работу»). Если на эту дату сотрудник уже числится как принятый и не уволен, тогда следует запрещать проведение.

    Пример такого усложнения может включать соединение с регистром сведений: ВЫБРАТЬ ПЕРВЫЕ 1 РегистрСведений.СостояниеСотрудников.Сотрудник ИЗ РегистрСведений.СостояниеСотрудников КАК РегистрСведенийСостояниеСотрудников ГДЕ РегистрСведенийСостояниеСотрудников.Сотрудник = &Сотрудник И РегистрСведенийСостояниеСотрудников.Период <= &ДатаДокумента // или другая логика И РегистрСведенийСостояниеСотрудников.Активен = ИСТИНА // Пример условия

    Это требует глубокого понимания структуры данных вашей конфигурации.

  2. Производительность запросов на больших объемах данных.

    Если в вашей базе данных сотни тысяч или миллионы документов «Прием на работу», и каждый из них имеет объемные табличные части, запросы к этим табличным частям могут стать ресурсоемкими. Это может замедлить процесс проведения документов.

    Для оптимизации мы можем рассмотреть следующие подходы:

    • Индексы: Убедитесь, что реквизит Сотрудник в табличной части документа (или в регистре сведений, если вы его используете) проиндексирован. Индексы значительно ускоряют поиск по условиям ГДЕ.
    • Оптимизация запроса: Использование ВЫБРАТЬ ПЕРВЫЕ 1 уже является хорошей оптимизацией, так как запрос прекращает работу после первого совпадения.
    • Кэширование: В некоторых случаях (хотя для ОбработкаПроведения это редко применимо из-за необходимости актуальных данных) можно использовать кэширование результатов, но для нашей задачи прямой запрос к базе данных более надежен.
  3. Информативность сообщения пользователю.

    Когда документ не проводится, пользователь должен ясно понимать причину. Сообщение типа «Проведение отменено» бесполезно. Наш пример кода уже включает в себя вывод конкретного имени сотрудника, что является хорошей практикой. Можно добавить ссылку на документ, в котором этот сотрудник уже оформлен, если это требуется по бизнес-логике (для этого потребуется немного изменить запрос, чтобы он возвращал также ссылку на найденный документ).

  4. Аналогичные механизмы в типовых конфигурациях.

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

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

← На главную