В процессе автоматизации торговой деятельности на платформе «1С:Предприятие» в конфигурации «Управление производственным предприятием» (УПП 1.3) или «Управление торговлей» (УТ 10.3) часто возникает задача автоматического закрытия просроченных заказов. Для этого используется регламентное задание, которое должно выявлять неактуальные заказы по определенным критериям и программно формировать документ «Закрытие заказов покупателей». Однако при реализации этого механизма разработчики часто сталкиваются со специфическим поведением документа: созданный объект оказывается пустым, данные в табличную часть не записываются, а сама структура документа вызывает вопросы. В этой статье мы подробно разберем, как правильно решить данную задачу, почему возникают ошибки заполнения и какие важные архитектурные нюансы необходимо учитывать.
При первом знакомстве с документом ЗакрытиеЗаказовПокупателей в конфигураторе разработчик может испытать недоумение. Открыв интерактивную форму документа в режиме «1С:Предприятие», мы видим множество информативных колонок: «Сумма заказа», «Осталось отгрузить», «Осталось оплатить», «Размещено», «Резерв», «Просрочено» и другие. Однако, попытавшись обратиться к табличной части Заказы программно, мы обнаруживаем, что в ней физически присутствуют всего три колонки:
ЗаказПокупателя — ссылка на закрываемый документ;ПричинаЗакрытияЗаказа — ссылка на элемент справочника причин закрытия;НомерСтроки — стандартное системное поле.Проанализируем эту ситуацию. Все остальные многочисленные поля, отображаемые на форме, являются виртуальными (расчетными). Они не хранятся в базе данных для этого документа, так как это привело бы к избыточному дублированию информации и нарушению принципов нормализации данных. Расчет этих показателей происходит динамически «на лету» в момент открытия формы или при интерактивном подборе заказов. Программа делает запросы к остаткам регистров накопления:
ЗаказыПокупателей — для вычисления сумм и количества товаров, которые осталось отгрузить или оплатить;ТоварыВРезервеНаСкладах — для получения информации о текущих складских резервах под этот заказ;РазмещениеЗаказовПокупателей — для анализа размещений в заказах поставщикам или в заказах на производство.Таким образом, при программном создании документа нам не требуется заполнять эти виртуальные поля. Для успешного проведения документа системе необходимы только сам заказ и причина его закрытия. При последующем интерактивном открытии созданного нами документа платформа автоматически рассчитает и отобразит всю необходимую информацию на форме.
Рассмотрим ситуацию, когда при выполнении программного кода строки добавляются, но реквизит ЗаказПокупателя остается пустым. Выясним причину, почему это происходит. Проанализируем типичный фрагмент кода, вызывающий проблемы:
// Проблемный вариант заполнения
Для каждого стр из Результат цикл
ЗаказыЗакрывающиеся = Закрытие.Заказы.Добавить();
ЗаказыЗакрывающиеся.ЗаказПокупателя = стр.ДокументРез;
ЗаказыЗакрывающиеся.ПричинаЗакрытияЗаказа = СсылкаНаПричину;
КонецЦикла;
Если после выполнения строки ЗаказыЗакрывающиеся.ЗаказПокупателя = стр.ДокументРез; значение остается пустым, то в 99% случаев проблема заключается в несоответствии типов данных. Платформа «1С:Предприятие» строго типизирует колонки табличных частей. Если колонка ожидает ссылку типа ДокументСсылка.ЗаказПокупателя, а ей присваивается значение другого типа (например, строка, уникальный идентификатор или ссылка на документ другого вида), то система не выдает ошибку времени выполнения, а просто «тихо» очищает поле, записывая туда ПустаяСсылка.
Посмотрим на возможные причины несоответствия типов:
стр.ДокументРез имеет составной тип данных или тип ДокументСсылка общего вида, из-за чего системе не удается неявно привести его к конкретному типу ДокументСсылка.ЗаказПокупателя.Для гарантированного решения этой проблемы рекомендуется явно типизировать получаемые из запроса данные и оптимизировать обращение к табличной части документа.
Разберем по шагам правильную методику создания и заполнения документа. Чтобы код работал стабильно и быстро, особенно в контексте регламентного задания на сервере, необходимо придерживаться следующих правил:
Документы.ЗакрытиеЗаказовПокупателей.СоздатьДокумент().Организация, Дата, ВидОперации и ОтражатьВУправленческомУчете.Рассмотрим оптимальный шаблон кода для автоматического заполнения документа:
// Создаем новый документ
НовыйДокумент = Документы.ЗакрытиеЗаказовПокупателей.СоздатьДокумент();
НовыйДокумент.Дата = ТекущаяДата();
НовыйДокумент.Организация = ВыбраннаяОрганизация;
НовыйДокумент.ВидОперации = Перечисления.ВидыОперацийЗакрытиеЗаказовПокупателей.ЗакрытиеЗаказов;
НовыйДокумент.Комментарий = "Автоматическое закрытие заказов регламентным заданием от " + ТекущаяДата();
// Заполняем признаки отражения в учете
НовыйДокумент.ОтражатьВУправленческомУчете = Истина;
// Получаем ссылку на табличную часть один раз перед циклом
ТабличнаяЧастьЗаказы = НовыйДокумент.Заказы;
Для Каждого СтрокаДанных Из РезультатВыборки Цикл
// Проверяем тип данных перед добавлением
Если ТипЗнч(СтрокаДанных.ЗаказПокупателя) = Тип("ДокументСсылка.ЗаказПокупателя") Тогда
НоваяСтрокаТЧ = ТабличнаяЧастьЗаказы.Добавить();
НоваяСтрокаТЧ.ЗаказПокупателя = СтрокаДанных.ЗаказПокупателя;
НоваяСтрокаТЧ.ПричинаЗакрытияЗаказа = СсылкаНаПричинуЗакрытия;
КонецЕсли;
КонецЦикла;
// Записываем и проводим документ
Попытка
НовыйДокумент.Записать(РежимЗаписиДокумента.Проведение);
ЗаписатьВЛог("Документ успешно проведен: " + НовыйДокумент.Ссылка);
Исключение
// Если провести не удалось, записываем только объект, чтобы не потерять данные
НовыйДокумент.Записать(РежимЗаписиДокумента.Запись);
ЗаписатьВЛог("Не удалось провести документ. Ошибка: " + ОписаниеОшибки());
КонецПопытки;
Проанализируем бизнес-логику процесса закрытия заказов. В документе ЗакрытиеЗаказовПокупателей предусмотрено несколько видов операций (перечисление ВидыОперацийЗакрытиеЗаказовПокупателей). Крайне важно выбрать правильный вид операции для вашего регламентного задания:
ЗаказыПокупателей, обнуляя все невыполненные обязательства по отгрузке и оплате. Также снимаются все резервы и размещения. Этот вид операции используется, когда заказ больше не будет выполняться (например, клиент отказался от покупки или истек жизненный цикл сделки).Важно: ошибочный выбор вида операции при автоматическом закрытии может привести к искажению управленческой отчетности и потере заказов из плана продаж.
Поскольку автоматическое закрытие обычно выполняется в рамках регламентного задания, необходимо учитывать технические нюансы серверного выполнения:
Применяя описанные подходы, мы сможем создать надежный, быстродействующий и безопасный механизм автоматического закрытия заказов покупателей в конфигурациях на базе обычных форм платформы «1С:Предприятие 8».