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

Сквозные ДП

Концепция

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

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

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

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

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

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

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

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

Таблица 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, но разной длиной цепочки

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

2-уровневая цепочка:

Счёт [Договор] → Договор [Сумма]
OrderID: 1=Договор, 2=Сумма

3-уровневая цепочка:

Счёт [Договор] → Договор [Контрагент] → Контрагент [ИНН]
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

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

Код Severity Описание
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 для построения списка связей.

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

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

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

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

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

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

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

Подробнее: admin.md

Сквозной ДП типа «Таблица» — поведение UI (v2.267+)

Когда сквозной ДП ссылается на ДП-Таблицу в другой категории, UI-компонент таблицы загружает настройки через GET api/ep/tableSettings/{extParamId}/subcat/{subcatId}/{taskId}, передавая extParamId сквозного ДП (не ДП-источника). Это гарантирует, что бэкенд возвращает права в правильном контексте.

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

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

До v2.267: фронт передавал ID ДП-источника → права игнорировались → кнопки отображались даже при read-only, вызывая ошибку доступа при попытке действия.

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

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

-- 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

Проблема: Вызов PullThroughExtParam на каждое изменение может быть дорогим.

Решение: - Отключить @DenormalizeF для единичных изменений - Накапливать изменения и вызывать денормализацию пакетом - Использовать фоновый job для периодической синхронизации


Диагностика

Проверка всех сквозных ДП

-- Найти все сквозные ДП с ошибками
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 для просмотра промежуточных результатов
EXEC dbo.PullThroughExtParam 
    @TargetTaskID = 12345,
    @DebugF = 1;

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

Совместимость

  • MS SQL Server: 2016+
  • Использует: CTE, MERGE, table variables, window functions

Версия документа: 1.0
Дата: 2026-02-07