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