Как реализовать сохранение истории изменения каждой строки документа при создании корректировок?

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

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

В этой статье мы подробно разберем, как спроектировать систему, которая позволит пользователю увидеть полную «генеалогию» любой строки: от момента её появления в основном документе до всех трансформаций во всех корректировках.

Метод 1. Использование уникальных идентификаторов (RowID) и регистра сведений

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

Разберем реализацию по шагам:

  1. Добавление реквизита в ТЧ: В табличную часть вашего документа (например, СоставСметы) добавьте реквизит КлючСтроки с типом Строка(36) или УникальныйИдентификатор.
  2. Создание регистра сведений: Создадим непериодический регистр ИсторияСвязейСтрок.
    • Измерения: ИсходныйДокумент, ИсходныйКлюч, ТекущийДокумент, ТекущийКлюч.
    • Ресурсы: Количество, Сумма (для анализа долей при разделении).
  3. Программное управление: При копировании строки из основного документа в корректировку КлючСтроки сохраняется. При разделении строки программно создаются новые ключи, а в регистр записывается связь: старый ключ -> новые ключи.

Рассмотрим пример кода для генерации ключа при добавлении строки:


Процедура СоставСметыПриИзменении(Элемент)
    ТекущиеДанные = Элементы.СоставСметы.ТекущиеДанные;
    Если ТекущиеДанные <> Неопределено И ПустаяСтрока(ТекущиеДанные.КлючСтроки) Тогда
        ТекущиеДанные.КлючСтроки = Строка(Новый УникальныйИдентификатор());
    КонецЕсли;
КонецПроцедуры

Метод 2. Паттерн «Суррогатный справочник строк»

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

Проанализируем структуру:

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

При разделении строки выполняем следующие действия:

Такой подход позволяет строить отчеты по дереву справочника, используя стандартные механизмы запросов 1С.

Метод 3. Внедрение специализированных команд «Разделить» и «Объединить»

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

Посмотрим на алгоритм реализации команд:

  1. Запрет прямого редактирования: Сделаем колонки количества и суммы доступными только через специальные формы.
  2. Команда «Разделить»: Пользователь выделяет строку, нажимает кнопку. Открывается окно, где он указывает, на сколько частей разбить строку и в какой пропорции.
  3. Регистрация события: В момент нажатия «ОК» система должна не только создать новые строки в ТЧ, но и зафиксировать в скрытой служебной таблице документа (или регистре), что Строка №1 превратилась в Строку №5 и Строку №6.

Пример логики разделения:


// Примерная логика в обработчике команды "Разделить"
НоваяСтрока = Объект.Состав.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, ИсходнаяСтрока);
НоваяСтрока.КлючСтроки = Строка(Новый УникальныйИдентификатор());
// Фиксируем связь в структуре для последующей записи в регистр
РегистрироватьСвязь(ИсходнаяСтрока.КлючСтроки, НоваяСтрока.КлючСтроки, "Разделение");

Метод 4. Визуализация истории (Направленный граф)

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

1. Дерево значений на форме. Это самый простой способ. Мы рекурсивно обходим записи регистра связей и строим иерархию. Пользователь видит корень (строка изначальной сметы) и ветви (как она менялась в корректировках).

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

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

Опыт типовых решений (на примере 1С:ERP)

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

Важные рекомендации по хранению данных

Выясним, как обеспечить производительность системы при большом количестве корректировок:

Хранение «Слепка» (Snapshot): Чтобы при открытии истории не выполнять тяжелые рекурсивные запросы к регистру, можно при проведении каждой корректировки сохранять в специальный реквизит документа (тип ХранилищеЗначения) JSON-структуру текущего состояния связей. Это позволит мгновенно отрисовать историю, прочитав данные только из текущего объекта.

Контроль чистоты: Программисту важно реализовать проверку «целостности» при удалении корректировок. Если промежуточная корректировка удаляется, связи должны корректно перестроиться или заблокироваться, чтобы «генеалогическое древо» строки не разорвалось.

Подводя итог, можно сказать, что решение задачи требует комбинации трех элементов: уникальной идентификации строк (UUID), строгого интерфейсного контроля (команды разделения/объединения) и регистра связей для построения итогового отчета.

← На главную