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