Должен ли документ менять реквизиты справочника при проведении в 1С?

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

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

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

Рассмотрим ситуацию, в которой программист решил обновлять поле Организация в справочнике Лицензии при проведении документа передачи. На первый взгляд, все работает: открываем карточку лицензии и видим актуального владельца. Но давайте проанализируем последствия, с которыми столкнется система в процессе эксплуатации.

  1. Нарушение транзакционной целостности и отсутствие автоматического отката. Когда документ делает движения по регистрам, платформа берет на себя управление этими записями. Если пользователь нажмет «Отмена проведения», 1С автоматически удалит записи из регистров. Но если документ программно изменил реквизит справочника, платформа не знает, какое значение там было раньше. Нам придется вручную писать сложный код для «запоминания» старого состояния и возврата его обратно, что крайне ненадежно.
  2. Проблема перепроведения «задним числом». Это самый опасный момент. Представим, что Лицензия №1 была передана из Организации А в Организацию Б в марте, а затем в Организацию В в июне. В справочнике сейчас стоит «Организация В». Если бухгалтер решит перепровести мартовский документ (например, исправив в нем опечатку в номере), этот документ запишет в справочник «Организацию Б». В итоге данные в справочнике станут неактуальными, так как система «забудет», что лицензия уже давно уехала в Организацию В.
  3. Потеря истории изменений. Справочник хранит только текущее состояние. Если мы просто перезаписываем реквизит, мы навсегда теряем информацию о том, кто владел лицензией месяц или год назад. Мы не сможем построить отчет о движении лицензий между организациями, используя только данные справочника.
  4. Конфликты блокировок в многопользовательской среде. При записи элемента справочника объект блокируется целиком. Если один пользователь открыл карточку лицензии для редактирования описания, а в это время другой пользователь пытается провести документ передачи этой лицензии, система выдаст ошибку блокировки. Регистры лишены этой проблемы, так как они оптимизированы для параллельной записи движений разными документами.

Методологически верное решение: Регистр сведений

Вместо хранения переменной информации (владелец, состояние, местонахождение) в самом справочнике, проанализируем использование Периодического регистра сведений. Справочник в данном случае должен содержать только условно-постоянную информацию: серийный номер, название продукта, дату выпуска. Все, что меняется во времени, должно выноситься в регистр.

Рассмотрим алгоритм реализации через Регистр сведений МестонахождениеЛицензий:

  1. Создадим периодический регистр сведений (периодичность — В пределах секунды).
  2. Установим режим записи Подчинение регистратору. Это обеспечит жесткую связь записи регистра с документом.
  3. В качестве измерения укажем Лицензия (тип СправочникСсылка.Лицензии), в качестве ресурса — Организация (тип СправочникСсылка.Организации).

Теперь при проведении документа нам не нужно трогать справочник. Документ просто создает запись в регистре. Разберем пример кода в модуле проведения документа:


Процедура ОбработкаПроведения(Отказ, Режим)
    // Очищаем старые движения
    Движения.МестонахождениеЛицензий.Записывать = Истина;
    Движения.МестонахождениеЛицензий.Очистить();
    
    Для Каждого СтрокаТЧ Из ТабличнаяЧастьЛицензии Цикл
        НоваяЗапись = Движения.МестонахождениеЛицензий.Добавить();
        НоваяЗапись.Период = Дата;
        НоваяЗапись.Лицензия = СтрокаТЧ.Лицензия;
        НоваяЗапись.Организация = ОрганизацияПолучатель;
    КонецЦикла;
КонецПроцедуры

Как отображать текущее состояние в справочнике и списках

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

Проанализируем способы получения текущего владельца:

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

Использование регистров накопления для количественного учета

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

Регистр накопления позволит:

Пример структуры регистра накопления ОстаткиЛицензий (вид — Остатки):

При передаче лицензии документ сделает две записи: Расход по Организации-отправителю и Приход по Организации-получателю. Это классическая схема балансового учета, принятая в 1С.

Выводы и рекомендации

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

Рассмотрим краткий чек-лист при проектировании:

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

← На главную