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