При разработке конфигураций в 1С часто возникает задача отражения состояния объекта: например, когда при проведении документа бронирования номер в отеле должен помечаться как занятый, а при отмене проведения — освобождаться. Рассмотрим, почему при попытке прямого изменения справочника возникает ошибка, как её исправить и какой архитектурный подход является наиболее надежным.
Разберем типичный фрагмент кода в модуле объекта документа, который приводит к ошибке:
Процедура ОбработкаПроведения(Отказ, Режим)
Ном = Номер.ПолучитьОбъект();
Ном.Забронирован = Истина;
Ном.Записать();
КонецПроцедуры
Выясним причину появления ошибки. В платформе 1С каждый документ имеет стандартный системный реквизит Номер (строкового типа). Если пользовательский реквизит документа, ссылающийся на справочник, также назван Номер, то при обращении по имени без явного контекста платформа обращается к стандартному строковому номеру самого документа. Вызов метода ПолучитьОбъект() у строки приводит к исключению времени выполнения.
Также ошибка возникает в ситуации, когда реквизит-ссылка на справочник не заполнен (содержит Неопределено или пустую ссылку).
Разберем по шагам, как исправить прямое обращение к справочнику:
НомерОтеля, Комната или НомерКомнаты).Посмотрим на исправленный код модуля документа:
Процедура ОбработкаПроведения(Отказ, Режим)
Если ЗначениеЗаполнено(ЭтотОбъект.НомерОтеля) Тогда
ОбъектНомера = ЭтотОбъект.НомерОтеля.ПолучитьОбъект();
Если ОбъектНомера <> Неопределено Тогда
ОбъектНомера.Забронирован = Истина;
ОбъектНомера.Записать();
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Процедура ОбработкаУдаленияПроведения(Отказ)
Если ЗначениеЗаполнено(ЭтотОбъект.НомерОтеля) Тогда
ОбъектНомера = ЭтотОбъект.НомерОтеля.ПолучитьОбъект();
Если ОбъектНомера <> Неопределено Тогда
ОбъектНомера.Забронирован = Ложь;
ОбъектНомера.Записать();
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Проанализируем технические проблемы, к которым приводит хранение статуса непосредственно в реквизите справочника:
Для учета статусов и занятости в платформе 1С предназначен объект метаданных Регистр сведений. Рассмотрим правильную реализацию задачи через регистр сведений, подчиненный регистратору.
Разберем создание структуры данных по шагам:
СтатусыНомеров с режимом записи Подчинение регистратору.НомерОтеля (тип СправочникСсылка.НомераОтеля) и ресурс Занят (тип Булево) или Статус (тип ПеречислениеСсылка.СтатусыНомеров).Посмотрим на пример формирования движений в модуле документа:
Процедура ОбработкаПроведения(Отказ, Режим)
// Очищаем существующие движения и взводим флаг записи
Движения.СтатусыНомеров.Очистить();
Движения.СтатусыНомеров.Записывать = Истина;
// Формируем движение по регистру
Движение = Движения.СтатусыНомеров.Добавить();
Движение.Период = ЭтотОбъект.Дата;
Движение.НомерОтеля = ЭтотОбъект.НомерОтеля;
Движение.Занят = Истина;
КонецПроцедуры
Важное преимущество: при использовании движений по регистру платформенный механизм 1С автоматически очищает движения при отмене проведения документа. Программисту не требуется писать ручной код очистки в событии ОбработкаУдаленияПроведения.
Чтобы пользователи видели актуальный статус занятости в форме списка справочника, не нужно менять реквизиты самого справочника. Достаточно подключить регистр через запрос в свойствах динамического списка формы.
Разберем настройку запроса динамического списка:
Список включаем флаг Произвольный запрос.Посмотрим на текст запроса для динамического списка:
ВЫБРАТЬ
СправочникНомера.Ссылка КАК Ссылка,
СправочникНомера.Наименование КАК Наименование,
ЕСТЬNULL(СтатусыСрезПоследних.Занят, ЛОЖЬ) КАК Занят
ИЗ
Справочник.НомераОтеля КАК СправочникНомера
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СтатусыНомеров.СрезПоследних(&ТекущаяДата, ) КАК СтатусыСрезПоследних
ПО СправочникНомера.Ссылка = СтатусыСрезПоследних.НомерОтеля
В модуле формы в обработчике ПриСозданииНаСервере передаем текущую дату в параметры списка:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Список.Параметры.УстановитьЗначениеПараметра("ТекущаяДата", ТекущаяДатаСеанса());
КонецПроцедуры
После этого поле Занят можно вынести в колонки таблицы на форме и настроить условное оформление (например, выделение занятых номеров другим цветом текста или фона), сохранив при этом чистоту архитектуры и быстродействие базы данных.