В практике внедрения типовых решений на платформе 1С:Предприятие 8.3 часто возникает задача хранения истории изменений тех или иных свойств объекта. Стандартный механизм «Дополнительные реквизиты и сведения» по умолчанию не является периодическим — каждое новое значение просто затирает старое. Однако бизнес-процессы часто требуют возможности посмотреть, каким было значение реквизита месяц назад, или автоматически получать актуальное значение на конкретную дату.
Ситуация осложняется, если конфигурация находится на строгом сопровождении и использование расширений по каким-то причинам невозможно. В данной статье мы разберем по шагам несколько эффективных стратегий реализации периодичности данных, используя только штатные механизмы БСП (Библиотеки стандартных подсистем) и творческий подход к разработке.
Самый очевидный способ сохранить историю изменений — включить подсистему «Версионирование объектов». Рассмотрим, как это работает для нашей задачи.
Когда пользователь изменяет значение дополнительного реквизита, система создает новую версию объекта. В этой версии сохраняются и дополнительные сведения. Для реализации этого метода выполним следующие действия:
Проанализируем плюсы и минусы этого подхода. Главный плюс — полная прозрачность для пользователя. История доступна по кнопке «История изменений» в карточке объекта. Минус — программное извлечение значения на определенную дату требует работы с хранилищем значений в регистре СведенияООбъектах. Если нам нужно регламентным заданием получать «последнее» значение, придется программно десериализовать версию объекта.
Если нам нужно хранить небольшую историю изменений (например, 5–10 последних значений), мы можем применить метод «контейнера». Рассмотрим этот вариант подробнее.
Создадим два дополнительных реквизита для объекта:
ТекущееЗначение (тип, соответствующий данным).ИсторияИзменений (тип «Строка» неограниченной длины).В строковом реквизите мы будем хранить данные в формате JSON или XML. Структура может выглядеть следующим образом:
[
{"Дата": "2023-01-01", "Значение": "100"},
{"Дата": "2023-06-01", "Значение": "120"},
{"Дата": "2023-10-15", "Значение": "115"}
]
Для работы с такими данными нам потребуется внешняя обработка, которая будет выполнять роль интерфейса. Программа будет считывать строку, преобразовывать ее в таблицу значений для отображения пользователю, а при сохранении — упаковывать обратно в JSON. Посмотрим на пример кода для записи данных:
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ТаблицаИстории);
РезультатСтрокой = ЗаписьJSON.Закрыть();
// Далее записываем РезультатСтрокой в ДополнительныйРеквизит "ИсторияИзменений"
Малоизвестный, но крайне эффективный способ ведения периодических записей без кода — использование подсистемы «Заметки» из состава БСП. Рассмотрим, как приспособить этот механизм под наши нужды.
Заметки в 1С имеют автора и дату создания. Если договориться, что каждое изменение параметра фиксируется новой заметкой с определенным префиксом в заголовке, мы получаем готовую периодическую последовательность. Проанализируем преимущества:
Заметки.Если объем исторических данных велик или они представляют собой сложные структуры, мы можем использовать механизм присоединенных файлов. Почти ко всем ключевым справочникам в УТ 11 можно прикрепить файлы.
Рассмотрим алгоритм решения:
history.txt или data.json) и прикрепляем его к объекту.В этом случае 1С сама управляет историей (версиями) этого файла. Мы всегда можем программно обратиться к последней активной версии файла или просмотреть список всех версий через стандартную форму «Присоединенные файлы».
Для задач, где данные нужны в основном программе (регламентным заданиям), а не пользователю «в лоб», можно использовать системную таблицу ХранилищеОбщихНастроек. Это позволяет хранить произвольные данные (массивы, таблицы значений), привязывая их к уникальному ключу.
В качестве ключа удобно использовать Уникальный Идентификатор (GUID) объекта. Разберем пример записи периодической структуры данных:
КлючОбъекта = "ИсторияРеквизита_" + Строка(ОбъектСсылка.УникальныйИдентификатор());
СтруктураДанных = Новый Структура("Дата, Значение", ТекущаяДата(), НовоеЗначение);
// Читаем старую историю, добавляем новый элемент и сохраняем
История = ХранилищеОбщихНастроек.Загрузить(КлючОбъекта, "Данные");
Если История = Неопределено Тогда
История = Новый Массив;
КонецЕсли;
История.Добавить(СтруктураДанных);
ХранилищеОбщихНастроек.Сохранить(КлючОбъекта, "Данные", История);
Этот метод гарантирует сохранность данных при выгрузке/загрузке базы через .dt, так как настройки хранятся в системных таблицах БД. При этом конфигурация остается полностью типовой.
Выясним, какой метод лучше выбрать в зависимости от ситуации:
Таким образом, отсутствие возможности изменять конфигурацию не является непреодолимым препятствием. Комбинируя механизмы БСП и внешние обработки, можно реализовать полноценный функционал периодических реквизитов, сохраняя при этом систему на полной поддержке вендора.