При реализации интеграции 1С с внешними системами (например, сайтом или мобильным приложением) программисты часто сталкиваются с ситуацией, когда необходимые данные отображаются в карточке справочника, но физически не являются его реквизитами. Типичный пример — «Текущий статус», который может храниться в отдельном регистре сведений. В этой статье мы подробно разберем, как найти источник этих данных, связать справочник с перечислением и корректно выгрузить результат в XML-строку.
Прежде чем приступать к написанию кода, нам необходимо выяснить, где именно в базе данных хранится информация о статусе. В системе 1С данные, которые меняются со временем (такие как статусы заказов, лицевых счетов или цены), практически никогда не добавляются прямо в реквизиты справочника. Для этого используются Периодические регистры сведений.
Давайте проанализируем ситуацию, описанную в теме. На форме справочника аоЛицевыеСчета есть поле «Текущий статус», но в структуре самого справочника этого поля нет. Рассмотрим алгоритм поиска источника данных:
аоСтатусыЛицевыхСчетов).аоИсторияСтатусовЛС), где в «Измерениях» указан наш справочник, а в «Ресурсах» — само перечисление.Если данные хранятся в периодическом регистре сведений, то для получения актуального значения на текущий момент нам не нужно перебирать все записи регистра. В 1С для этого существует виртуальная таблица СрезПоследних. Проанализируем, как программно получить статус для конкретного элемента справочника:
// Пример получения статуса через менеджер регистра
СтатусЗаписи = РегистрыСведений.аоСтатусыЛицевыхСчетов.СрезПоследних(ТекущаяДата(), Новый Структура("ЛицевойСчет", СсылкаНаЛС));
Если СтатусЗаписи.Количество() > 0 Тогда
ТекущийСтатус = СтатусЗаписи[0].Статус;
КонецЕсли;
В исходном коде автора используется метод Выбрать(). Это допустимо для простых задач, но когда нам нужно связать справочник со статусом и отфильтровать закрытые счета, использование объекта Запрос становится обязательным. Это значительно ускоряет работу системы и снижает нагрузку на сервер.
Рассмотрим, как составить запрос, который сразу выберет лицевые счета, их контактную информацию и актуальный статус, отсекая при этом записи со статусом «Закрыт»:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЛицевыеСчета.Код КАК Код,
| ЛицевыеСчета.Абонент КАК Абонент,
| ЛицевыеСчета.Регион КАК Регион,
| ЛицевыеСчета.Город КАК Город,
| ЛицевыеСчета.Улица КАК Улица,
| ЛицевыеСчета.НомерДома КАК НомерДома,
| ЛицевыеСчета.НомерКвартиры КАК НомерКвартиры,
| СтатусыСрезПоследних.Статус КАК Статус
|ИЗ
| Справочник.аоЛицевыеСчета КАК ЛицевыеСчета
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.аоСтатусыЛицевыхСчетов.СрезПоследних(&Период, ) КАК СтатусыСрезПоследних
| ПО ЛицевыеСчета.Ссылка = СтатусыСрезПоследних.ЛицевойСчет
|ГДЕ
| СтатусыСрезПоследних.Статус <> ЗНАЧЕНИЕ(Перечисление.аоСтатусыЛицевыхСчетов.Закрыт)";
Запрос.УстановитьПараметр("Период", ТекущаяДата());
Выборка = Запрос.Выполнить().Выбрать();
Теперь разберем процесс записи полученных данных в XML. Для этого мы будем использовать объект ЗаписьXML. Важно помнить, что при выгрузке перечислений мы можем передавать либо их синоним (текст для пользователя), либо имя метаданных (код для разработчика сайта).
Выясним, как правильно записать строковое представление статуса в XML-узел:
Запись.ЗаписатьНачалоЭлемента("Status");
// Получаем строковое значение перечисления (синоним)
ТекстСтатуса = Строка(Выборка.Статус);
Запись.ЗаписатьТекст(ТекстСтатуса);
Запись.ЗаписатьКонецЭлемента();
Если для интеграции на стороне сайта требуется уникальный идентификатор статуса (например, для программной обработки), лучше использовать метод XMLСтрока(Выборка.Статус) или обращаться к имени значения перечисления через метаданные.
Сведем все полученные знания в единую функцию. Проанализируем структуру кода, которая позволяет эффективно выгружать данные абонентов вместе с их телефонами и статусами:
Функция ВыгрузитьАбонентовВXML(СпособВыгрузки)
Запись = Новый ЗаписьXML;
Если СпособВыгрузки = "Файл" Тогда
Запись.ОткрытьФайл("C:\Exports\Abonents.xml");
Иначе
Запись.УстановитьСтроку();
КонецЕсли;
Запись.ЗаписатьОбъявлениеXML();
Запись.ЗаписатьНачалоЭлемента("Abonents");
// Используем запрос для получения данных из справочника и регистра
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ * ИЗ Справочник.аоЛицевыеСчета КАК ЛС"; // Упрощенно
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Запись.ЗаписатьНачалоЭлемента("Abonent");
Запись.ЗаписатьНачалоЭлемента("Code");
Запись.ЗаписатьТекст(Строка(Выборка.Код));
Запись.ЗаписатьКонецЭлемента();
Запись.ЗаписатьНачалоЭлемента("Name");
Запись.ЗаписатьТекст(Строка(Выборка.Абонент));
Запись.ЗаписатьКонецЭлемента();
// Работа со статусом из перечисления
Запись.ЗаписатьНачалоЭлемента("Status");
Если ЗначениеЗаполнено(Выборка.Статус) Тогда
Запись.ЗаписатьТекст(Строка(Выборка.Статус));
Иначе
Запись.ЗаписатьТекст("Не определен");
КонецЕсли;
Запись.ЗаписатьКонецЭлемента();
// Выгрузка контактной информации из табличной части
ТабличнаяЧасть = Выборка.Ссылка.КонтактнаяИнформация;
Для Каждого СтрокаТЧ Из ТабличнаяЧасть Цикл
Если СтрокаТЧ.Тип = Перечисления.ТипыКонтактнойИнформации.Телефон Тогда
Запись.ЗаписатьНачалоЭлемента("Phone");
Запись.ЗаписатьТекст(Строка(СтрокаТЧ.НомерТелефона));
Запись.ЗаписатьКонецЭлемента();
КонецЕсли;
КонецЦикла;
Запись.ЗаписатьКонецЭлемента(); // Abonent
КонецЦикла;
Запись.ЗаписатьКонецЭлемента(); // Abonents
Результат = ?(СпособВыгрузки = "Файл", "Выгружено в файл", Запись.Закрыть());
Возврат Результат;
КонецФункции
Для успешного связывания справочника с данными перечисления, которые хранятся отдельно, мы выполнили следующие шаги:
Выбрать() на Запрос с левым соединением таблиц.ПеречислениеСсылка.Такой подход гарантирует, что ваша интеграция будет работать быстро, а данные на сайте всегда будут соответствовать актуальному состоянию базы 1С.