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