Как реализовать автоматическую смену статуса книги при проведении документа в 1С?

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

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

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

Вариант 1: Прямое изменение реквизита справочника (учебный метод)

Этот способ чаще всего выбирают начинающие разработчики или студенты при написании курсовых работ. Его суть заключается в том, чтобы найти объект справочника, изменить его реквизит и записать изменения непосредственно в модуле проведения документа. Рассмотрим, как это выглядит в коде процедуры ОбработкаПроведения.

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

  1. Переходим в модуль документа ВыдачаКниги.
  2. Находим предопределенную процедуру ОбработкаПроведения.
  3. Пишем код получения объекта справочника через ссылку, указанную в документе.

Пример кода для реализации этой задачи:


Процедура ОбработкаПроведения(Отказ, РежимПроведения)
    
    // Проверяем, заполнена ли ссылка на экземпляр книги в документе
    Если Не ЗначениеЗаполнено(ЭкземплярКниги) Тогда
        Сообщить("Не выбран экземпляр книги!");
        Отказ = Истина;
        Возврат;
    КонецЕсли;

    // Получаем объект справочника для редактирования
    ОбъектЭкземпляр = ЭкземплярКниги.ПолучитьОбъект();
    
    // Устанавливаем новый статус из перечисления
    ОбъектЭкземпляр.Статус = Перечисления.СтатусыКниг.Выдана;
    
    // Записываем изменения в базу данных
    Попытка
        ОбъектЭкземпляр.Записать();
    Исключение
        Сообщить("Не удалось обновить статус книги: " + ОписаниеОшибки());
        Отказ = Истина;
    КонецПопытки;

КонецПроцедуры

Важное замечание: Метод ПолучитьОбъект() считывает все данные элемента из базы в оперативную память и блокирует его. Это работает, если в документе одна книга, но если у вас табличная часть с сотнями книг, выполнение Записать() в цикле приведет к серьезному замедлению работы системы.

Почему опытные разработчики критикуют этот метод?

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

Вариант 2: Использование регистров сведений (профессиональный метод)

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

Вместо создания реквизита в справочнике ЭкземплярыКниги, мы создаем регистр сведений СостояниеКниг со следующими параметрами:

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

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


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

Проверка текущего статуса перед выдачей

Независимо от выбранного метода, мы должны убедиться, что книга вообще доступна для выдачи. Проанализируем ситуацию: что будет, если библиотекарь попытается выдать книгу, которая уже выдана другому читателю или вовсе списана? Система должна это пресечь.

Рассмотрим, как добавить проверку перед основным кодом проведения:


// В начале процедуры ОбработкаПроведения
ТекущийСтатус = ЭкземплярКниги.Статус; // Если используем реквизит справочника

Если ТекущийСтатус = Перечисления.СтатусыКниг.Выдана Тогда
    Сообщить("Ошибка! Книга уже находится на руках у читателя.");
    Отказ = Истина;
    Возврат;
ИначеЕсли ТекущийСтатус = Перечисления.СтатусыКниг.Списана Тогда
    Сообщить("Ошибка! Данный экземпляр книги списан из фонда.");
    Отказ = Истина;
    Возврат;
КонецЕсли;

Оптимизация работы с табличной частью

Если в вашем документе ВыдачаКниги предполагается выбор нескольких книг в табличной части (например, список СоставКниг), использование метода ПолучитьОбъект() в цикле станет критической ошибкой производительности. Разберем, как правильно обрабатывать списки данных.

Вместо обращения к базе за каждой книгой по отдельности, мы должны:

  1. Собрать все ссылки на книги из табличной части в массив.
  2. Одним запросом проверить их текущие статусы.
  3. Если все книги свободны — выполнить массовое обновление.

Посмотрим на пример эффективного кода:


Процедура ОбработкаПроведения(Отказ, РежимПроведения)

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

    // Если ошибок нет, переходим к смене статуса...
    // (Здесь код изменения статуса через регистр или справочник)
КонецПроцедуры

Визуализация статусов для пользователя

Чтобы библиотекарь мог быстро ориентироваться в списке фонда, недостаточно просто менять данные в базе. Разберем, как сделать работу удобнее. В форме списка справочника ЭкземплярыКниги мы можем настроить условное оформление.

Например, мы можем настроить систему так, чтобы:

Если вы выбрали путь с Регистром сведений, то для отображения статуса в списке книг вам потребуется использовать динамический список с произвольным запросом. В запросе нужно будет соединить таблицу справочника с виртуальной таблицей СрезПоследних регистра сведений. Это обеспечит актуальность данных в режиме реального времени без лишней нагрузки на систему.

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

← На главную