Как правильно спроектировать базу данных «Библиотека» в 1С и настроить отбор книг на руках?

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

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

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

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

  1. Блокировки базы данных. Изменение элементов справочника из транзакции проведения документа (процедура ОбработкаПроведения в модуле объекта) приводит к блокировке таблиц справочника. В многопользовательском режиме это вызовет серьезные задержки и ошибки блокировок у других пользователей.
  2. Нарушение последовательности и актуальности данных. Если пользователь решит отменить проведение документа или перепровести старый документ задним числом, данные в справочнике станут неактуальными. Справочник хранит только одно текущее значение и не имеет истории изменений.
  3. Принцип разделения данных. Документы предназначены для регистрации событий и совершения движений в регистрах. Справочники должны содержать условно-постоянную информацию. Динамическое состояние объектов (где сейчас книга, у какого читателя она находится) должно храниться исключительно в регистрах.

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

Выбор регистра: Сведений или Накопления?

Разберем по шагам, какой тип регистра больше подходит для нашей задачи. Участники форума часто спорят, стоит ли использовать регистр накопления или регистр сведений:

Регистр накопления предназначен для хранения числовых показателей, которые изменяются по принципу «приход/расход». Он отлично подходит, если нам нужно вести количественный учет общего фонда (например, сколько всего книг «Война и мир» числится в библиотеке). Однако ресурсы регистра накопления могут быть только числовыми. Мы не сможем записать в ресурс регистра ссылку на читателя.

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

При выдаче книги документ делает запись в этот регистр. В ресурсе Читатель указывается конкретный человек, а в МестоРазмещения — статус «На руках».

Архитектура справочников: разделение на «Издания» и «Экземпляры»

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

Правильное решение заключается в разделении сущностей на два справочника:

  1. Справочник «Издания» (Номенклатура): хранит общие сведения о произведении (Название, Автор, Издательство, ISBN, Год издания).
  2. Справочник «Экземпляры книг»: этот справочник делается подчиненным справочнику «Издания». Каждый его элемент соответствует реальной физической книге, лежащей на полке. Здесь хранятся уникальный инвентарный номер, штрихкод и текущее состояние.

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

Реализация отбора книг «на руках» в документе «Возврат книг»

Перейдем к практической реализации задачи: как сделать так, чтобы при выборе читателя в документе возврата выводились только те книги, которые за ним числятся? Рассмотрим подробнее два основных способа реализации этой логики.

Способ А. Программное заполнение табличной части

Этот способ наиболее удобен для пользователя. В форму документа добавляется команда «Заполнить книги на руках». При ее вызове система выполняет запрос к регистру сведений и автоматически заполняет табличную часть документа.

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


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

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

Способ Б. Программный отбор при начале выбора книги

Если нам нужно, чтобы пользователь сам выбирал книгу из списка, но видел только доступные для возврата позиции, мы можем настроить отбор в обработчике события НачалоВыбора поля табличной части Книга.

Разберем этот метод по шагам:

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

Пример реализации обработчика события:


&НаКлиенте
Процедура КнигиКнигаНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    
    // Отменяем стандартное открытие формы выбора
    СтандартнаяОбработка = Ложь;
    
    Если Не ЗначениеЗаполнено(Объект.Читатель) Тогда
        ПоказатьПредупреждение(, "Сначала выберите читателя!");
        Возврат;
    КонецЕсли;
    
    // Получаем массив книг, которые находятся у читателя
    МассивКниг = ПолучитьКнигиНаРукахНаСервере(Объект.Читатель);
    
    ПараметрыВыбора = Новый Структура;
    
    // Формируем отбор по ссылке "В списке"
    Отбор = Новый Структура("Ссылка", Новый ФиксированныйМассив(МассивКниг));
    ПараметрыВыбора.Вставить("Отбор", Отбор);
    
    // Открываем форму выбора справочника ЭкземплярыКниг с установленным отбором
    ОткрытьФорму("Справочник.ЭкземплярыКниг.ФормаВыбора", ПараметрыВыбора, Элемент);
    
КонецПроцедуры

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

Заключение

Мы проанализировали основные архитектурные аспекты проектирования конфигурации «Библиотека». Использование периодического регистра сведений для контроля местонахождения книг и отказ от изменения справочников при проведении документов позволяет построить стабильную, масштабируемую систему учета. Разделение справочника книг на «Издания» и уникальные «Экземпляры» решает проблему дублирования книг, а механизмы запросов к виртуальным таблицам обеспечивают удобный и быстрый отбор данных для пользователей при оформлении возвратов.

← На главную