Как реализовать связь между контрагентами и контактными лицами с учетом должностей в 1С?

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

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

Шаг 1. Создание базовых справочников

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

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

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

Шаг 2. Реализация связи «Многие-ко-многим»

Главная сложность задачи — необходимость обеспечить привязку одного контактного лица к разным контрагентам с указанием разных должностей. Например, Иванова Мария является главным бухгалтером в организации «Альфа» и кассиром в организации «Бета». Добавление простого реквизита Должность в справочник контактных лиц будет ошибкой, так как должность привязана к конкретному месту работы, а не к самому человеку.

Посмотрим на два варианта решения этой архитектурной проблемы.

Вариант 1: Использование табличной части (Учебный вариант)

Если в рамках вашего обучения вы еще не проходили регистры сведений, каноничным и правильным решением будет использование табличной части. Создадим в справочнике Контрагенты табличную часть, назовем ее, например, КонтактныеЛицаКонтрагента. В этой табличной части создадим два реквизита:

  1. КонтактноеЛицо — тип СправочникСсылка.КонтактныеЛица.
  2. Должность — тип Строка (или ссылка на отдельный справочник должностей, если нужно строгий учет).

Такой подход полностью решает поставленную задачу: справочник контактных лиц остается независимым, а Иванову Марию можно выбрать в табличных частях разных контрагентов, указав соответствующую должность в каждой строке.

Вариант 2: Использование Регистра сведений (Профессиональный стандарт)

В реальных типовых конфигурациях 1С для подобных задач применяются независимые непериодические регистры сведений. Этот способ избавляет от блокировок всего справочника контрагентов при обновлении контактных данных. Чтобы реализовать этот подход, создадим регистр сведений ДолжностиКонтактныхЛиц со следующей структурой:

Шаг 3. Служебная обработка «Проверка контрагентов»

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

Если мы используем структуру с табличной частью, наш запрос будет использовать левое соединение справочника с его же табличной частью. Те записи, где данные из табличной части равны NULL, и будут нашими искомыми контрагентами без контактов. Рассмотрим пример кода:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    Контрагенты.Ссылка КАК Контрагент
    |ИЗ
    |    Справочник.Контрагенты КАК Контрагенты
    |        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты.КонтактныеЛицаКонтрагента КАК ТЧКонтакты
    |        ПО Контрагенты.Ссылка = ТЧКонтакты.Ссылка
    |ГДЕ
    |    Контрагенты.ЭтоГруппа = ЛОЖЬ
    |    И ТЧКонтакты.КонтактноеЛицо ЕСТЬ NULL";

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

Пока Выборка.Следующий() Цикл
    Сообщить("Нет контактного лица у контрагента: " + Выборка.Контрагент);
КонецЦикла;

В данном запросе условие Контрагенты.ЭтоГруппа = ЛОЖЬ (или использование виртуального поля НЕ Контрагенты.ЭтоГруппа) отвечает за исключение папок из результатов поиска. Условие ЕСТЬ NULL надежно отсеивает те элементы справочника, у которых табличная часть абсолютно пуста.

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

← На главную