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