При разработке нетипового функционала в конфигурациях на базе ERP-платформы (1С:Управление торговлей 11, 1С:Комплексная автоматизация 2, 1С:ERP) программисты часто сталкиваются с необходимостью создания собственных документов продажи или оплаты. Типичный бизнес-кейс — создание документа "Передача заказа курьеру". Задача такого документа — оперативно списать задолженность с покупателя по его заказу и одновременно перевесить этот долг на курьера (или службу доставки), который становится материально ответственным за товар и деньги.
Однако в современных версиях УТ 11 включена по умолчанию и является обязательной «Новая архитектура взаиморасчетов» (онлайн-взаиморасчеты). Попытка просто записать движения в регистр накопления РасчетыСКлиентами «по-старинке» гарантированно приводит к тому, что стандартные отчеты (например, «Ведомость расчетов с клиентами») перестают сходиться, ломается логика закрытия месяца, а система не видит новые долги. В этой статье мы подробно разберем, как устроен механизм онлайн-взаиморасчетов изнутри, как правильно встроить в него свой документ программно и какую готовую методическую альтернативу предоставляет сама система без изменения кода конфигурации.
---
Прежде чем переходить к коду, давайте проанализируем, как система обрабатывает данные по расчетам в режиме онлайн. При включенной константе НоваяАрхитектураВзаиморасчетов проведение документов разделено на два связанных контура:
РасчетыСКлиентами и РасчетыСКлиентамиПланОплат. Но эти движения носят лишь предварительный характер!РасчетыСКлиентамиПоСрокам и РасчетыСКлиентамиПоДокументам. Движения в них делает исключительно служебный документ «Регистратор расчетов». Сами накладные или оплаты напрямую в эти регистры писать не могут.Служебный документ Регистратор расчетов создается и обновляется платформой автоматически при проведении документов. Программа отслеживает изменения через специальную очередь — регистр сведений ЗаданияКРаспределениюРасчетовСКлиентами. Если вы просто запишете движения в РасчетыСКлиентами, но не добавите запись в таблицу заданий к распределению, система не пересчитает аналитический контур, и ваш долг зависнет или отобразится некорректно.
---
Если бизнес-логика требует создания именно отдельного документа (например, «Передача заказа курьеру»), нам необходимо полностью «подружить» его с платформенными механизмами. Разберем этот процесс по шагам.
Прежде всего, наш новый документ должен получить права на работу с регистрами расчетов. Для этого:
РасчетыСКлиентами (и при необходимости РасчетыСКлиентамиПланОплат) и добавим наш новый документ в список Регистраторов.ОпределяемыйТип.РасчетныйДокументСКлиентом — это позволит системе использовать документ как первичный источник расчетов.ОпределяемыйТип.ОбъектРасчетов — если сам наш документ в будущем может выступать объектом расчетов (например, по нему напрямую будут приниматься оплаты от курьера).Рассмотрим, какие именно записи должен делать документ в регистре РасчетыСКлиентами при проведении. Нам необходимо решить две задачи: закрыть долг клиента по заказу и открыть долг курьера. На основе успешного практического опыта выделим правильные хозяйственные операции:
1. Списание долга с заказа клиента:
Для этого в регистр пишется две строки (Расход и Приход), которые имитируют оплату:
Поступление оплаты от клиента (или Взаимозачет задолженности).ЗаказКлиента (или ОбъектРасчетов): указываем исходный заказ покупателя.Сумма и КОплате со знаком плюс (приход) и аналогично делаем расходное движение для закрытия задолженности.2. Образование долга по курьеру:
Для создания дебиторской задолженности за курьером формируется приходное движение:
Планирование по заказу клиента (или аналогичная операция отгрузки).ЗаказКлиента (или ОбъектРасчетов): в качестве объекта расчетов выступает наш новый документ «Передача заказа курьеру» или договор с курьером.КОплате.Посмотрим на пример кода формирования движений в модуле проведения нашего документа:
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
// Инициализируем таблицу движений по регистру Расчеты с клиентами
Движения.РасчетыСКлиентами.Записывать = Истина;
ТаблицаДвижений = Движения.РасчетыСКлиентами.ВыгрузитьКолонки();
// 1. Движение: Списание долга с заказа клиента (Расход)
НоваяСтрока = ТаблицаДвижений.Добавить();
НоваяСтрока.Период = Дата;
НоваяСтрока.ВидДвижения = ВидДвиженияНакопления.Расход;
НоваяСтрока.Активность = Истина;
НоваяСтрока.ХозяйственнаяОперация = ХозяйственныеОперации.ВзаимозачетЗадолженности;
НоваяСтрока.Партнер = ИсходныйКлиент;
НоваяСтрока.Контрагент = ИсходныйКонтрагент;
НоваяСтрока.Организация = Организация;
НоваяСтрока.ОбъектРасчетов = ИсходныйЗаказКлиента;
НоваяСтрока.Валюта = ВалютаДокумента;
НоваяСтрока.Сумма = СуммаДокумента;
НоваяСтрока.КОплате = СуммаДокумента;
// 2. Движение: Образование долга на курьере (Приход)
НоваяСтрокаКурьер = ТаблицаДвижений.Добавить();
НоваяСтрокаКурьер.Период = Дата;
НоваяСтрокаКурьер.ВидДвижения = ВидДвиженияНакопления.Приход;
НоваяСтрокаКурьер.Активность = Истина;
НоваяСтрокаКурьер.ХозяйственнаяОперация = ХозяйственныеОперации.ПланированиеПоЗаказуКлиента;
НоваяСтрокаКурьер.Партнер = ПартнерКурьер;
НоваяСтрокаКурьер.Контрагент = КонтрагентКурьер;
НоваяСтрокаКурьер.Организация = Организация;
// Наш документ выступает в качестве объекта расчетов
НоваяСтрокаКурьер.ОбъектРасчетов = Ссылка;
НоваяСтрокаКурьер.Валюта = ВалютаДокумента;
НоваяСтрокаКурьер.КОплате = СуммаДокумента;
// Загружаем подготовленные движения в регистр
Движения.РасчетыСКлиентами.Загрузить(ТаблицаДвижений);
// Регистрируем задание на пересчет онлайн-взаиморасчетов (Шаг 3)
РегистрацияЗаданийВзаиморасчетов();
КонецПроцедуры
Для того чтобы система запустила автоматический онлайн-расчет и создала служебный документ Регистратор расчетов, мы обязаны внести записи в регистр сведений ЗаданияКРаспределениюРасчетовСКлиентами. Выясним, как это реализовать в коде:
Процедура РегистрацияЗаданийВзаиморасчетов()
// Подготавливаем таблицу для регистрации заданий
ТаблицаЗаданий = Новый ТаблицаЗначений;
ТаблицаЗаданий.Колонки.Добавить("Регистратор", Новый ОписаниеТипов("ДокументСсылка.ПередачаЗаказаКурьеру"));
ТаблицаЗаданий.Колонки.Добавить("ОбъектРасчетов", Новый ОписаниеТипов("СправочникСсылка.ОбъектыРасчетов"));
// Добавляем задание по исходному заказу клиента
НовоеЗадание = ТаблицаЗаданий.Добавить();
НовоеЗадание.Регистратор = Ссылка;
НовоеЗадание.ОбъектРасчетов = ИсходныйЗаказКлиента;
// Добавляем задание по новому объекту расчетов (курьеру)
НовоеЗаданиеКурьер = ТаблицаЗаданий.Добавить();
НовоеЗаданиеКурьер.Регистратор = Ссылка;
НовоеЗаданиеКурьер.ОбъектРасчетов = Ссылка;
// Вызываем стандартный метод БСП для записи заданий к распределению
ВзаиморасчетыСервер.ЗарегистрироватьЗаданияКРаспределениюРасчетовСКлиентами(ТаблицаЗаданий);
КонецПроцедуры
Система должна идентифицировать наш документ в алгоритмах закрытия месяца и распределения расчетов. Обязательно внесите изменения в переопределяемые общие модули:
ВзаиморасчетыСерверПереопределяемый — здесь необходимо зарегистрировать тип нашего документа, чтобы система понимала, относится ли он к категории накладных (увеличивающих долг) или оплат (уменьшающих долг).РеглУчетВыборкиСерверПовтИсп (функции ЭтоОбъектРасчетов и ЭтоРасчетныйДокумент) — это потребуется, если вы планируете в будущем формировать проводки по регламентированному учету (счета 62, 76) для этого документа.---
Как справедливо замечают опытные архитекторы 1С, глубокое вмешательство в алгоритмы онлайн-взаиморасчетов — задача трудоемкая и несет в себе риски при последующих обновлениях конфигурации. Зачастую аналогичного бизнес-эффекта можно достичь, используя исключительно типовой функционал.
Рассмотрим, как красиво решить задачу переноса долга с клиента на курьера стандартными средствами программы:
Заказ клиента и документ Реализация товаров и услуг. На клиенте повисает дебиторская задолженность.Взаимозачет задолженности с видом операции «Перенос дебиторской задолженности».
Заказ клиента.Поступление безналичных ДС или Приходный кассовый ордер, где плательщиком выступает курьер, а объектом расчетов — документ взаимозачета задолженности.Приобретение услуг и прочих активов (закупка услуг доставки у курьера). Наша организация становится должна курьеру за услуги. Затем с помощью еще одного документа Взаимозачет задолженности мы схлопываем наш долг курьеру за доставку и долг курьера нам за товары.Этот методический путь полностью безопасен для обновлений и гарантирует 100% корректность всех отчетов по взаиморасчетам «из коробки».
---
Мы проанализировали два полярных подхода к решению задачи. Если вы выбираете программный путь разработки собственного документа, обязательно следуйте правилам новой архитектуры: регистрируйте определяемые типы, делайте парные движения по регистру РасчетыСКлиентами и не забывайте регистрировать задания к распределению расчетов. Если же в приоритете стабильность обновлений системы — используйте элегантную схему с типовым документом Взаимозачет задолженности, которая решает задачу переноса долга на курьера без написания единой строки кода.