При работе с торговыми конфигурациями, такими как 1С:Управление торговлей (УТ 11), ERP или Комплексная автоматизация, часто возникает необходимость визуализировать в списке заказов данные, которые напрямую в заголовке документа не хранятся. Одной из таких задач является вывод даты первой оплаты. Рассмотрим подробно, как реализовать этот функционал, учитывая современные архитектурные требования и механизмы платформы 1С:Предприятие 8.3.
Прежде чем приступать к написанию кода, проанализируем структуру данных. В системе существует два принципиально разных понятия «первой оплаты», и важно не перепутать источники данных:
ЭтапыГрафикаОплаты документа ЗаказКлиента. Эти данные показывают, когда клиент должен заплатить согласно договору или соглашению.РасчетыСКлиентами) или регистре сведений СостоянияЗаказовКлиентов. Это реальная дата поступления денежных средств на расчетный счет или в кассу.Разберем способы реализации для обоих случаев, ориентируясь на то, что изменять типовую конфигурацию крайне не рекомендуется.
Если ваша задача — вывести в список дату первого платежа, который зафиксирован в графике оплаты самого заказа, мы можем модифицировать запрос динамического списка. Рассмотрим, как это сделать правильно, чтобы не потерять в производительности.
Напрямую соединять документ с его табличной частью в динамическом списке нельзя, так как это приведет к дублированию строк (на каждый этап оплаты появится копия строки заказа). Нам нужно использовать группировку. Проанализируем пример запроса:
ВЫБРАТЬ
ДокументЗаказКлиента.Ссылка КАК Ссылка,
ДокументЗаказКлиента.Номер КАК Номер,
ДокументЗаказКлиента.Дата КАК Дата,
МинимальныеДатыОплаты.ДатаПлатежа КАК ДатаПервойПлановойОплаты
ИЗ
Документ.ЗаказКлиента КАК ДокументЗаказКлиента
ЛЕВОЕ СОЕДИНЕНИЕ (
ВЫБРАТЬ
Этапы.Ссылка КАК Ссылка,
МИНИМУМ(Этапы.ДатаПлатежа) КАК ДатаПлатежа
ИЗ
Документ.ЗаказКлиента.ЭтапыГрафикаОплаты КАК Этапы
СГРУППИРОВАТЬ ПО
Этапы.Ссылка
) КАК МинимальныеДатыОплаты
ПО МинимальныеДатыОплаты.Ссылка = ДокументЗаказКлиента.Ссылка
В данном примере мы создаем вложенный запрос, который выбирает минимальную дату для каждого заказа, и соединяем его с основной таблицей документов по ссылке. Это обеспечит вывод ровно одной даты для каждой строки списка.
Если требуется вывести дату реального платежа, использование сложных соединений с регистрами в динамическом списке может существенно замедлить работу системы. Разберем более профессиональный подход — использование расширения конфигурации.
Рассмотрим пошагово алгоритм действий:
ЗаказКлиента.ДатаПервойФактическойОплаты (тип: Дата). Это позволит хранить значение непосредственно в документе, и оно будет доступно для выбора в настройках списка без сложных запросов.ПоступлениеБезналичныхДенежныхСредств, ПриходныйКассовыйОрдер).ДатаПервойФактическойОплаты еще не заполнен, записываем туда дату текущего платежа.Пример кода для обработчика (в модуле расширения):
&После("ОбработкаПроведения")
Процедура Расш1_ЗаполнитьДатуОплаты(Отказ, РежимПроведения)
Для Каждого СтрокаРасчетов Из ЭтотОбъект.РасшифровкаПлатежа Цикл
Если ТипЗнч(СтрокаРасчетов.ОбъектОплаты) = Тип("ДокументСсылка.ЗаказКлиента") Тогда
ЗаказОбъект = СтрокаРасчетов.ОбъектОплаты.ПолучитьОбъект();
Если ЗаказОбъект.ДатаПервойФактическойОплаты = '00010101' Тогда
ЗаказОбъект.ДатаПервойФактическойОплаты = ЭтотОбъект.Дата;
ЗаказОбъект.Записать(РежимЗаписиДокумента.Запись);
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
В типовой УТ 11 существует служебный регистр сведений СостоянияЗаказовКлиентов. Система сама обновляет его данные при изменении заказов и оплат. Это наиболее эффективный источник данных для динамических списков.
Выясним причину, почему это удобно: данный регистр уже содержит рассчитанные проценты оплаты и отгрузки. Чтобы вывести дату первой оплаты через этот механизм, можно:
СостоянияЗаказовКлиентов (через расширение) ресурс ДатаПервойОплаты.ЛЕВОЕ СОЕДИНЕНИЕ с этим регистром.Посмотрим на пример того, как это может выглядеть в запросе динамического списка (фрагмент):
ВЫБРАТЬ
ДокументЗаказКлиента.Ссылка,
ДокументЗаказКлиента.Дата,
ЕСТЬNULL(СостоянияЗаказов.ДатаПервойОплаты, ДАТАВРЕМЯ(1, 1, 1)) КАК ДатаПервойОплаты
ИЗ
Документ.ЗаказКлиента КАК ДокументЗаказКлиента
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СостоянияЗаказовКлиентов КАК СостоянияЗаказов
ПО СостоянияЗаказов.Заказ = ДокументЗаказКлиента.Ссылка
Проанализируем технические нюансы, которые могут возникнуть при реализации:
Производительность: Старайтесь избегать вложенных запросов и соединений с большими таблицами движений в динамическом списке. Оптимальный вариант — хранение готовой даты в реквизите документа или в специализированном регистре сведений.
Обновление данных: Если вы решили хранить дату в реквизите заказа, не забудьте написать обработку, которая заполнит это поле для уже существующих документов в базе (старых заказов).
Использование событий формы: Метод ПриПолученииДанныхНаСервере можно использовать для небольших списков, но он крайне не рекомендуется для списков с тысячами записей, так как вызывает дополнительные обращения к базе данных на каждый цикл отрисовки экрана, что может привести к «тормозам» интерфейса у пользователя.
Таким образом, для реализации задачи наиболее правильным путем будет использование расширения с добавлением реквизита в ЗаказКлиента и подпиской на проведение платежей. Это обеспечит максимальную скорость работы списка и чистоту типовой конфигурации.