В процессе разработки в системе 1С:Предприятие часто возникает необходимость вывести на форму документа оперативную информацию, которая не хранится в самом документе, но важна для пользователя. Одной из таких задач является получение данных о продажах по конкретному контрагенту за предыдущий месяц. Рассмотрим, как это реализовать в управляемых формах, какие методы использовать и на что обратить внимание в современных конфигурациях, таких как УТ 11, ERP или КА 2.
Представим ситуацию: менеджер открывает заказ клиента и хочет сразу видеть объем закупок этого контрагента за прошлый месяц. Для решения этой задачи нам нужно обратиться к регистру накопления, который хранит данные о продажах. Основной вопрос заключается в том, как сделать это максимально эффективно и правильно с точки зрения архитектуры 1С.
Проанализируем два основных способа получения данных:
Обороты().Разберем каждый из этих подходов по шагам.
Многие разработчики, привыкшие к работе в «обычных формах» (1С 8.2 и ранее), ищут способ получить данные одной строкой кода. В платформе действительно существует метод Обороты() у объекта РегистрНакопленияМенеджер. Рассмотрим пример реализации такой функции на сервере.
Выясним причину, почему этот метод редко используется в типовых решениях: он возвращает ТаблицаЗначений или ВыборкаИзРезультатаЗапроса, и хотя он кажется компактным, он менее гибкий, чем полноценный запрос. Тем не менее, посмотрим на пример кода:
&НаСервере
Функция ПолучитьПродажиЗаПрошлыйМесяц(ВыбранныйКонтрагент)
// Определяем период: начало и конец предыдущего месяца
ДатаНачала = НачалоМесяца(ДобавитьМесяц(ТекущаяДата(), -1));
ДатаОкончания = КонецМесяца(ДобавитьМесяц(ТекущаяДата(), -1));
// Формируем структуру отбора
Отбор = Новый Структура;
Отбор.Вставить("Контрагент", ВыбранныйКонтрагент);
// Обращаемся к менеджеру регистра (имя регистра зависит от конфигурации)
// В УТ 11 это может быть ВыручкаИСебестоимостьПродаж
ТаблицаОборотов = РегистрыНакопления.ВыручкаИСебестоимостьПродаж.Обороты(ДатаНачала, ДатаОкончания, Отбор, "СуммаВыручки");
Если ТаблицаОборотов.Количество() > 0 Тогда
Возврат ТаблицаОборотов[0].СуммаВыручки;
Иначе
Возврат 0;
КонецЕсли;
КонецФункции
Важный момент: в управляемых формах обращение к объекту РегистрыНакопления доступно только на стороне сервера. Поэтому вызов этой функции из формы должен происходить внутри серверной процедуры.
Профессиональная разработка в 1С подразумевает использование механизма запросов. Это позволяет системе оптимально построить план выполнения на уровне SQL и задействовать индексы виртуальных таблиц. Проанализируем, как составить такой запрос к регистру накопления.
Рассмотрим структуру запроса к виртуальной таблице Обороты. Нам необходимо передать параметры периода и условие по контрагенту непосредственно в параметры виртуальной таблицы, чтобы база данных не считывала лишнюю информацию.
&НаСервереБезКонтекста
Функция ПолучитьСуммуПродажЗапросом(КонтрагентСсылка)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СУММА(ВыручкаОбороты.СуммаВыручкиОборот) КАК Сумма
|ИЗ
| РегистрНакопления.ВыручкаИСебестоимостьПродаж.Обороты(&НачалоПериода, &КонецПериода, , Контрагент = &Контрагент) КАК ВыручкаОбороты";
// Рассчитываем даты
ТекущаяДата = ТекущаяДатаСеанса();
Запрос.УстановитьПараметр("НачалоПериода", НачалоМесяца(ДобавитьМесяц(ТекущаяДата, -1)));
// Для точности используем Границу, чтобы включить последнюю секунду месяца
КонецМесяца = КонецМесяца(ДобавитьМесяц(ТекущаяДата, -1));
Запрос.УстановитьПараметр("КонецПериода", Новый Граница(КонецМесяца, ВидГраницы.Включая));
Запрос.УстановитьПараметр("Контрагент", КонтрагентСсылка);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Если ВыборкаДетальныеЗаписи.Следующий() Тогда
Возврат ВыборкаДетальныеЗаписи.Сумма;
КонецЕсли;
Возврат 0;
КонецФункции
Обратите внимание на использование объекта Граница. В 1С это считается "хорошим тоном", так как позволяет гарантированно захватить все движения, произошедшие ровно в 23:59:59 последнего дня месяца.
Разберем ситуацию, упомянутую в обсуждении: в современных конфигурациях на базе УТ 11 (или ERP 2) привычного регистра Продажи может не существовать или он используется для других целей.
Основные регистры для анализа продаж в актуальных версиях:
ВыручкаИСебестоимостьПродаж — основной регистр, где фиксируются финансовые результаты продаж.РасчетыСКлиентами — если нужно узнать объем задолженности или оплат.Типовые общие модули — часто в конфигурациях уже есть функции типа ПродажиСервер.ПолучитьПродажиЗаПериод(). Прежде чем писать свой код, рекомендуется изучить состав общих модулей.Посмотрим на пример того, как интегрировать получение данных в логику управляемой формы. Лучше всего делать это при изменении контрагента или при открытии формы.
&НаКлиенте
Процедура КонтрагентПриИзменении(Элемент)
// Вызываем серверную функцию для получения данных
ОбъемЗакупок = ПолучитьСуммуПродажЗапросом(Объект.Контрагент);
// Выводим информацию пользователю (например, в декорацию или реквизит формы)
ТекстИнформации = "Продажи за прошлый месяц: " + ОбъемЗакупок + " руб.";
КонецПроцедуры
Подведем итог нашему анализу:
РегистрыНакопления) возможна только &НаСервере.ВыручкаИСебестоимостьПродаж, а не в Продажи.Использование этих принципов позволит вам создавать стабильные и быстрые решения, которые будут легко поддерживаться другими разработчиками.