Перейти к содержанию

Сквозные ДП

Документ описывает сквозные дополнительные параметры (ДП) — специальный тип ExtParam, автоматически протягивающий значение через цепочку лукапов. Для администраторов и разработчиков. Разделы: бизнес-сценарий, структура данных (таблицы БД), правила валидности цепочки, основные процедуры (PullThroughExtParam, ExtParamTroughSettingsValidate и др.), настройка доступа, сценарии использования, типичные ошибки, диагностика.

Сквозной ДП (дополнительный параметр) — это специальный тип ExtParam, который автоматически «протягивает» значение из связанной задачи через цепочку лукапов (LookUpField). Вместо хранения собственного значения он отображает значение из задачи-источника.

Бизнес-сценарий

Предположим, у вас есть связанные задачи:

  • Счёт на оплату → связан с Договором → связан с Контрагентом
  • У контрагента есть поле ИНН
  • Вам нужно видеть ИНН контрагента прямо в карточке счёта

Традиционный подход: Создать ДП «ИНН контрагента» в счёте и вручную копировать значение. Проблема: При изменении ИНН в контрагенте нужно обновлять все счета.

Решение через сквозной ДП: Создать сквозной ДП, который автоматически показывает актуальное значение ИНН из связанного контрагента.

Пример цепочки

Цепочка сквозного ДП на примере счёта, договора и контрагента:

Задача "Счёт"          Задача "Договор"       Задача "Контрагент"
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│ [Договор]       │───►│ [Контрагент]    │───►│ [ИНН]           │
│ (LookUpField)   │    │ (LookUpField)   │    │ (Text)          │
│ ID=200          │    │ ID=300          │    │ ID=100          │
│ OrderID=1       │    │ OrderID=2       │    │ OrderID=3       │
│                 │    │                 │    │ = "7701234567"  │
│ [ИНН контр.]    │    └─────────────────┘    └─────────────────┘
│ (Through)       │                                      ▲
│ ID=500 ═════════╪══════════════════════════════════════╝
└─────────────────┘        значение автоматически копируется

В интерфейсе цепочка задаётся в настройках сквозного ДП, в блоке «Настройка пути по ДП»: последовательность ДП, по которым определяется значение (порядок важен; последний ДП — источник значения, остальные — ссылки на задачу).

Настройки сквозного ДП: тип «Through» и блок «Настройка пути по ДП» с цепочкой

Структура данных

Таблица dbo.ExtParamTroughSettings

Хранит настройки цепочки для каждого сквозного ДП.

Поле Описание
ExtParamID ID сквозного ДП (тип 'Through')
TargetExtParamID ID ДП на очередном шаге цепочки
OrderID Номер шага (1 = первый лукап от целевой задачи, max = источник данных)

Пример настройки для сквозного ДП «ИНН контрагента» (ID=500):

ExtParamID TargetExtParamID OrderID Описание
500 200 (Договор) 1 Шаг 1: первый лукап от счёта
500 300 (Контрагент) 2 Шаг 2: второй лукап
500 100 (ИНН) 3 Шаг 3: источник данных

Таблица dbo.ExtParams:

Справочник всех дополнительных параметров.

Типы ExtParam:

  • Through — сквозной ДП (протягивает значение по цепочке)
  • LookUpField — обычный лукап (один к одному)
  • MultiSlctSubcatTasks — мультилукап (один ко многим)
  • Text, Checkbox, NumericValue, Money, Date, Datetime — простые поля

Таблицы значений:

Значения ДП хранятся в нескольких таблицах:

  • ExtParamValues — основные значения ДП (текст, числа, даты, bool)
  • ExtParamValueSelectedTasks — выбранные задачи (для лукапов и мультилукапов)
  • ExtParamSelectUsersValues — выбранные пользователи
  • ExtParamSelectUsersValuesGroups — выбранные группы
  • ExtParamSelectUsersValuesOrgUnits — выбранные оргединицы
  • FileStorageFileToExtParamLinks — прикреплённые файлы к ДП

Правила валидности цепочки

Обязательные требования

Сквозной ДП следует полностью настроить — задать и валидировать цепочку — до добавления в категорию задач.

Цепочка считается валидной при выполнении требований:

  1. Минимум 2 записи в ExtParamTroughSettings для каждого сквозного ДП
  2. Максимум 3 записи (поддерживаются только 2-х и 3-х уровневые цепочки)
  3. OrderID должны быть непрерывны от 1 до count (без пропусков)
  4. Все шаги кроме последнего (OrderID < max) должны быть типа LookUpField
  5. Последний шаг (OrderID = max) — источник данных (любой тип, включая LookUpField)
  6. Источник не может быть типа Through (сквозной от сквозного)
  7. Лукапы в цепочке НЕ должны быть мультилукапами (только LookUpField, не MultiSlctSubcatTasks)
  8. Запрещено: несколько сквозных в одной категории с одним SourceExtParamID, но разной длиной цепочки

Примеры валидных конфигураций:

Счёт [Договор] → Договор [Сумма]
OrderID: 1=Договор, 2=Сумма
Счёт [Договор] → Договор [Контрагент] → Контрагент [ИНН]
OrderID: 1=Договор, 2=Контрагент, 3=ИНН

Примеры НЕвалидных конфигураций:

Мультилукап в цепочке:

Счёт [Договоры (multi)] → Договор [Контрагент]
Проблема: недетерминированность — какой из договоров выбрать?

Разные длины к одному источнику:

В категории "Счета":
- Сквозной ДП #1: Договор → ИНН (2 уровня)
- Сквозной ДП #2: Договор → Контрагент → ИНН (3 уровня)
Проблема: конфликт путей к одному источнику

Пропуск в OrderID:

OrderID: 1, 3 (нет 2)
Проблема: невозможно построить полную цепочку

Основные процедуры

1. dbo.PullThroughExtParam

Назначение: Синхронизация значений сквозных ДП — копирование данных из задачи-источника в целевую задачу. В интерфейсе полный перерасчёт запускает кнопка «Синхронизировать значение для всех задач» в карточке сквозного ДП.

Параметры:

Параметр Описание
@StartTaskID ID задачи-источника (откуда брать данные)
@StartExtParamID ID ДП-источника
@TargetTaskID ID целевой задачи (куда копировать)
@TargetExtParamID ID сквозного ДП
@DenormalizeF Вызывать ли денормализацию после синхронизации
@DebugF Режим отладки

Режимы работы:

Входные параметры Поведение
@StartTaskID + @StartExtParamID указаны От конкретной задачи-источника вниз по цепочке
@TargetTaskID + @TargetExtParamID указаны Только конкретная целевая пара
Все NULL Полная пересинхронизация всех сквозных ДП

Алгоритм работы:

  1. Построить список связей (DstTaskID, DstExtParamID) → (SrcTaskID, SrcExtParamID) с помощью функции TaskThroughPath
  2. Дедуплицировать (если несколько путей ведут к одной цели, выбрать один детерминированно)
  3. Для каждой таблицы выполнить MERGE:
  4. ExtParamSelectUsersValues — выбранные пользователи
  5. ExtParamSelectUsersValuesGroups — выбранные группы
  6. ExtParamSelectUsersValuesOrgUnits — выбранные оргединицы
  7. ExtParamValueSelectedTasks — выбранные задачи (лукапы/мультилукапы)
  8. FileStorageFileToExtParamLinks — прикреплённые файлы
  9. ExtParamValues — основные значения (текст, числа, даты)
  10. Вызвать денормализацию изменённых задач (если @DenormalizeF = 1)

Пример вызова:

-- Пересинхронизировать все сквозные ДП для конкретной задачи
EXEC dbo.PullThroughExtParam 
    @TargetTaskID = 12345,
    @DenormalizeF = 1;

-- Обновить все зависимые задачи при изменении источника
EXEC dbo.PullThroughExtParam 
    @StartTaskID = 67890,
    @StartExtParamID = 100,
    @DenormalizeF = 1;

2. dbo.ExtParamTroughSettingsValidate

Назначение: Проверка корректности настроек сквозных ДП.

Параметры:

Параметр Описание
@ExtParamID ID конкретного сквозного ДП (NULL = проверить все)
@FixOrderIDGapsF Автоматически исправить пропуски в OrderID

Проверяемые ошибки:

Код Уровень Описание
NO_SETTINGS ERROR Нет настроек цепочки
CHAIN_TOO_SHORT ERROR Меньше 2 элементов
CHAIN_TOO_LONG ERROR Больше 3 элементов
ORDERID_NOT_FROM_1 ERROR Цепочка не начинается с 1
ORDERID_GAPS ERROR Пропуски в OrderID
DUPLICATE_ORDERID ERROR Дублирование OrderID
TARGET_EP_NOT_FOUND ERROR TargetExtParamID не существует
INTERMEDIATE_NOT_LOOKUP ERROR Промежуточный элемент не LookUpField
MULTILOOKUP_IN_CHAIN ERROR Мультилукап в цепочке
SUBCAT_MISMATCH ERROR Несогласованность категорий
SELF_REFERENCE ERROR Ссылка на себя
MIXED_CHAIN_LENGTHS ERROR Разные длины к одному источнику
TARGET_IS_THROUGH WARNING Источник тоже сквозной

Примеры:

-- Проверить все сквозные ДП
EXEC dbo.ExtParamTroughSettingsValidate;

-- Проверить конкретный ДП
EXEC dbo.ExtParamTroughSettingsValidate @ExtParamID = 500;

-- Автоматически исправить пропуски в OrderID
EXEC dbo.ExtParamTroughSettingsValidate @FixOrderIDGapsF = 1;

3. dbo.ExtParamTroughSettingsSet

Назначение: Создание/изменение/удаление настроек сквозного ДП.

Параметры:

Параметр Описание
@TargetExtParamID ID сквозного ДП (обязательный)
@PathExtParamIDs Таблица с цепочкой ExtParamID (тип dbo.id_tbl_type)
@ValidateOnlyF Только проверить без сохранения
@DebugF Режим отладки

Примеры:

-- Создать 2-уровневую цепочку: Договор → ИНН
DECLARE @path dbo.id_tbl_type;
INSERT INTO @path (ID) VALUES (200), (100);
EXEC dbo.ExtParamTroughSettingsSet 
    @TargetExtParamID = 500, 
    @PathExtParamIDs = @path;

-- Создать 3-уровневую цепочку: Договор → Контрагент → ИНН
DECLARE @path dbo.id_tbl_type;
INSERT INTO @path (ID) VALUES (200), (300), (100);
EXEC dbo.ExtParamTroughSettingsSet 
    @TargetExtParamID = 500, 
    @PathExtParamIDs = @path;

-- Удалить настройки (передать пустой путь)
DECLARE @path dbo.id_tbl_type;
EXEC dbo.ExtParamTroughSettingsSet 
    @TargetExtParamID = 500, 
    @PathExtParamIDs = @path;

-- Только проверить без сохранения
EXEC dbo.ExtParamTroughSettingsSet 
    @TargetExtParamID = 500, 
    @PathExtParamIDs = @path, 
    @ValidateOnlyF = 1;

4. dbo.TaskThroughPath (функция)

Назначение: Разворачивание цепочки связей для построения путей от задачи-источника к целевым задачам.

Возвращает: Таблицу с парами (DstTaskID, DstExtParamID) → (SrcTaskID, SrcExtParamID)

Алгоритм:

  1. Найти все сквозные ДП (ExtParamType = 'Through')
  2. Для каждого проверить валидность цепочки в ExtParamTroughSettings
  3. Рекурсивно пройти по цепочке:
  4. Начало: задача с целевым сквозным ДП + первый лукап (OrderID=1)
  5. Рекурсия:
    • Взять TargetExtParamID для текущего OrderID
    • Найти в ExtParamValueSelectedTasks задачу, на которую ссылается этот лукап
    • Перейти к OrderID + 1
  6. Конец: OrderID = max, найден источник данных

Используется: Внутри PullThroughExtParam для построения списка связей.

Настройка доступа

Доступ пользователя к сквозному ДП определяется как доступ к обычному полю: чтение, чтение+запись или нет доступа.

Расчёт учитывает три уровня доступа пользователя к целевому параметру в задаче-источнике: нет чтения целевого параметра; есть чтение, нет записи; есть и чтение, и запись.

Параметр «Учитывать настройки доступа по целевому ДП»

Карточка сквозного ДП: настройка пути, кнопка «Синхронизировать значение для всех задач» и флаг «Учитывать настройки доступа по целевому ДП»

Когда включен — доступ рассчитывается как логическое И настроек сквозного и целевого ДП (обе должны разрешать):

Доступ к сквозному Доступ к целевому Результат
нет доступа чтение+запись не видит
чтение+запись чтение+запись чтение+запись
чтение+запись нет доступа не видит

Когда выключен — чтение определяется только по сквозному ДП, но при отсутствии прав на целевое поле оно становится доступным только для чтения:

Доступ к сквозному Доступ к целевому Результат
нет доступа чтение+запись не видит
чтение+запись чтение+запись чтение+запись
чтение+запись нет доступа только чтение

Подробнее: Настройка ДП

Сквозной ДП типа «Таблица» — поведение в интерфейсе: когда сквозной ДП ссылается на ДП-Таблицу в другой категории, доступность кнопок таблицы определяется по правам на сам сквозной ДП, а не на ДП-источник.

Ожидаемое поведение:

Доступ к сквозному ДП Результат в интерфейсе
Только чтение Кнопки «Добавить строку», «Удалить», «Редактировать» скрыты
Чтение + запись Кнопки отображаются

Сценарии использования

Создание новой цепочки

Пример создания цепочки целиком:

-- 1. Убедитесь что все ДП созданы:
--    - Счёт имеет ДП "Договор" (ID=200, тип LookUpField)
--    - Договор имеет ДП "Контрагент" (ID=300, тип LookUpField)
--    - Контрагент имеет ДП "ИНН" (ID=100, тип Text)
--    - Счёт имеет ДП "ИНН контрагента" (ID=500, тип Through)

-- 2. Создайте настройки цепочки
DECLARE @path dbo.id_tbl_type;
INSERT INTO @path (ID) VALUES 
    (200),  -- OrderID=1: Договор
    (300),  -- OrderID=2: Контрагент
    (100);  -- OrderID=3: ИНН (источник)

EXEC dbo.ExtParamTroughSettingsSet 
    @TargetExtParamID = 500, 
    @PathExtParamIDs = @path;

-- 3. Проверьте настройки
EXEC dbo.ExtParamTroughSettingsValidate @ExtParamID = 500;

-- 4. Выполните первоначальную синхронизацию
EXEC dbo.PullThroughExtParam @DenormalizeF = 1;

Обработка изменений

Когда вызывать PullThroughExtParam:

  1. При изменении лукапа в цепочке:

    -- Пользователь изменил договор в счёте
    EXEC dbo.PullThroughExtParam 
        @TargetTaskID = @TaskID_Счёт,
        @TargetExtParamID = 500,  -- ИНН контрагента
        @DenormalizeF = 1;
    

  2. При изменении значения в источнике:

    -- Изменили ИНН в контрагенте → обновить все зависимые счета
    EXEC dbo.PullThroughExtParam 
        @StartTaskID = @TaskID_Контрагент,
        @StartExtParamID = 100,  -- ИНН
        @DenormalizeF = 1;
    

  3. При создании новой задачи с лукапами:

    -- Создали новый счёт и выбрали договор
    EXEC dbo.PullThroughExtParam 
        @TargetTaskID = @NewTaskID,
        @DenormalizeF = 1;
    

Типичные ошибки и решения

Ошибки конфигурации цепочек сквозных ДП и рекомендации по устранению.

Ошибка: MULTILOOKUP_IN_CHAIN — в цепочке используется мультилукап вместо обычного.

Пример проблемы:

Счёт [Договоры (multi)] → Договор [Контрагент] → Контрагент [ИНН]

Почему это плохо:

  • Если счёт связан с 3 договорами, непонятно какой из них выбрать
  • row_number() дедупликация даст случайный результат
  • Значение сквозного ДП будет «прыгать» при каждом запуске

Решение: заменить мультилукап на обычный лукап (один к одному) или изменить бизнес-логику.


Ошибка: MIXED_CHAIN_LENGTHS

Причина: Несколько сквозных ДП в одной категории ведут к одному источнику, но через цепочки разной длины.

Пример проблемы:

В категории "Счета":
- Сквозной ДП "ИНН-1": Договор → ИНН (2 уровня)
- Сквозной ДП "ИНН-2": Договор → Контрагент → ИНН (3 уровня)

Почему это плохо:

  • Путь к одному источнику должен быть единственным
  • Разные пути могут привести к конфликтам при синхронизации

Решение: Унифицировать длину цепочек — все сквозные ДП к одному источнику должны идти через одинаковый путь.


Производительность: вызов PullThroughExtParam на каждое изменение может быть дорогим. Рекомендации: отключить @DenormalizeF для единичных изменений; накапливать изменения и вызывать денормализацию пакетом; использовать фоновое задание для периодической синхронизации.


Диагностика

Проверка всех сквозных ДП: найти все сквозные ДП с ошибками через EXEC dbo.ExtParamTroughSettingsValidate — результат покажет ExtParamID, ExtParamName, ErrorCode, ErrorMessage, Severity.

-- Найти все сквозные ДП с ошибками
EXEC dbo.ExtParamTroughSettingsValidate;

-- Результат покажет:
-- - ExtParamID
-- - ExtParamName
-- - ErrorCode
-- - ErrorMessage
-- - Severity (ERROR/WARNING)

Проверка конкретной цепочки

Посмотреть настройки конкретного сквозного ДП:

-- Посмотреть настройки для конкретного сквозного ДП
SELECT 
    epts.ExtParamID,
    ep_through.ExtParamName AS ThroughParamName,
    epts.OrderID,
    epts.TargetExtParamID,
    ep_target.ExtParamName AS TargetParamName,
    ep_target.ExtParamType AS TargetParamType
FROM dbo.ExtParamTroughSettings epts
JOIN dbo.ExtParams ep_through ON epts.ExtParamID = ep_through.ExtParamID
JOIN dbo.ExtParams ep_target ON epts.TargetExtParamID = ep_target.ExtParamID
WHERE epts.ExtParamID = 500
ORDER BY epts.OrderID;

Отладка синхронизации: запустить с @DebugF = 1 для просмотра промежуточных результатов — список построенных связей, количество обновлённых записей в каждой таблице, список задач для денормализации.

-- Запустить с @DebugF = 1 для просмотра промежуточных результатов
EXEC dbo.PullThroughExtParam 
    @TargetTaskID = 12345,
    @DebugF = 1;

-- Увидите:
-- - Список построенных связей (DstTaskID → SrcTaskID)
-- - Количество обновлённых записей в каждой таблице
-- - Список задач для денормализации

Совместимость: требования к окружению — MS SQL Server 2016+, используются CTE, MERGE, table variables, window functions.