Как программно создать и заполнить документ «Операция» в 1С:Бухгалтерия 3.0 без автозаписи?

Программист 1С v8.3 (Управляемые формы) Бухгалтерский учет IT и автоматизация бизнеса
← На главную

В практике разработки на платформе «1С:Предприятие 8.3» часто возникает задача автоматизировать рутинный ввод данных. Один из классических сценариев — программное создание документа «Операция, введенная вручную» (в конфигурации он называется ОперацияБух) с заполнением его табличной части из внешней обработки или по результатам анализа других документов. Однако стандартные методы создания и заполнения здесь наталкиваются на серьезное архитектурное препятствие: документ нельзя записывать в базу до того, как пользователь примет окончательное решение о его сохранении или отказе.

В рамках этой статьи мы подробно разберем, почему обычные методы заполнения табличных частей не работают для этого документа, проанализируем внутреннее устройство «Операции», а также разработаем универсальное и безопасное решение для управляемых форм конфигурации «Бухгалтерия предприятия, редакция 3.0».

В чем заключается главная сложность?

Для большинства документов в «1С» задача решается тривиально: мы создаем новый объект на сервере, заполняем его реквизиты и табличные части, затем передаем этот объект на форму или открываем его форму с параметрами заполнения. Однако с документом ОперацияБух этот фокус не сработает.

Выясним причину этого поведения. У документа «Операция» физически отсутствует табличная часть для хранения проводок. Этот документ выступает исключительно в роли регистратора движения для регистра бухгалтерии Хозрасчетный. На управляемой форме документа проводки выводятся через специальный реквизит формы — коллекцию ХозрасчетныйНаборЗаписей (в зависимости от релиза имя может незначительно отличаться, но суть остается прежней — это набор записей регистра, привязанный к форме).

Пока новый документ не записан, у него нет уникальной ссылки (значение Ссылка пустое). Без ссылки невозможно создать и сохранить набор записей регистра бухгалтерии, так как поле Регистратор не может быть пустым. Если мы попытаемся заполнить свойство Движения.Хозрасчетный у нового объекта на сервере, а затем просто откроем форму, пользователь увидит пустую таблицу проводок. Вся информация будет утеряна, так как форма при открытии попытается прочитать движения еще не существующего в базе документа и затрет наши программно добавленные строки.

Единственный надежный способ решить эту задачу — выполнять заполнение не самого прикладного объекта на сервере, а непосредственно коллекции данных на управляемой форме до того, как эта форма будет показана пользователю.

Пошаговый алгоритм решения задачи

Для того чтобы программно открыть заполненную, но не записанную «Операцию», мы выполним следующие шаги:

  1. Получим форму нового документа ОперацияБух без ее немедленного вывода на экран.
  2. Программно заполним основные реквизиты шапки документа (организацию, дату, содержание) непосредственно в реквизите формы Объект.
  3. В цикле добавим строки в коллекцию набора записей формы (ХозрасчетныйНаборЗаписей).
  4. Для каждого счета дебета и кредита вызовем специализированные процедуры общего модуля БП 3.0, чтобы система автоматически настроила видимость, типы и доступность субконто на форме.
  5. Заполним аналитику (субконто), количество, суммы и другие необходимые показатели.
  6. Покажем готовую и заполненную форму пользователю.

Рассмотрим детально реализацию каждого шага на примере программного кода.

Программная реализация заполнения формы

Ниже представлен готовый к использованию код, который можно разместить в модуле управляемой формы внешней обработки или в команде формы. Обратите внимание на разделение выполнения кода на клиенте и сервере.


&НаКлиенте
Процедура СоздатьОперациюБезЗаписи(Команда)
    
    // Шаг 1: Получаем форму нового документа
    ПараметрыФормы = Новый Структура;
    ФормаДокумента = ПолучитьФорму("Документ.ОперацияБух.ФормаОбъекта", ПараметрыФормы);
    
    // Шаг 2: Заполняем реквизиты шапки
    ФормаДокумента.Объект.Дата = ТекущаяДата();
    ФормаДокумента.Объект.Организация = ПолучитьОрганизациюПоУмолчанию();
    ФормаДокумента.Объект.Содержание = "Программное заполнение операции";
    
    // Шаг 3: Заполнение табличной части (набора записей регистра на форме)
    // В качестве примера заполним операцию по переносу затрат
    НоваяСтрока = ФормаДокумента.ХозрасчетныйНаборЗаписей.Добавить();
    
    // Заполняем период и организацию для строки движения (это критически важно!)
    НоваяСтрока.Период = ФормаДокумента.Объект.Date; // Или ФормаДокумента.Объект.Дата
    НоваяСтрока.Организация = ФормаДокумента.Объект.Организация;
    НоваяСтрока.Активность = Истина;
    
    // Устанавливаем счета учета
    НоваяСтрока.СчетДт = ПолучитьСчетПоКоду("20.01");
    НоваяСтрока.СчетКт = ПолучитьСчетПоКоду("10.01");
    
    // Шаг 4: Инициализируем субконто на форме через типовые механизмы БП 3.0
    ОбработатьИзменениеСчетаНаФорме(ФормаДокумента, "Дт", НоваяСтрока);
    ОбработатьИзменениеСчетаНаФорме(ФормаДокумента, "Кт", НоваяСтрока);
    
    // Шаг 5: Заполнение аналитики (субконто)
    // Обратите внимание: субконто заполняются по индексам СубконтоДт1, СубконтоДт2 и т.д.
    НоваяСтрока.СубконтоДт1 = ПолучитьНоменклатурнуюГруппу(); // Первое субконто для счета 20.01
    НоваяСтрока.СубконтоКт1 = ПолучитьМатериал();             // Первое субконто для счета 10.01
    
    // Заполняем суммовые и количественные показатели
    НоваяСтрока.Сумма = 15000;
    НоваяСтрока.КоличествоКт = 10;
    
    // Шаг 6: Открываем готовую форму пользователю
    ФормаДокумента.Открыть();
    
КонецПроцедуры

Для корректного подключения аналитики нам потребуется вспомогательная клиент-серверная процедура, которая имитирует интерактивный выбор счета пользователем. Это гарантирует, что все динамические связи на управляемой форме отработают штатно.

Разберем реализацию этой процедуры подробнее:


&НаКлиентеНаСервереБезКонтекста
Процедура ОбработатьИзменениеСчетаНаФорме(Форма, ДтКт, СтрокаТаблицы)
    
    // Настраиваем структуры полей для передачи в общие модули БП 3.0
    ПоляФормы = Новый Структура("Субконто1,Субконто2,Субконто3");
    ПоляФормы.Субконто1 = "ХозрасчетныйСубконто" + ДтКт + "1";
    ПоляФормы.Субконто2 = "ХозрасчетныйСубконто" + ДтКт + "2";
    ПоляФормы.Субконто3 = "ХозрасчетныйСубконто" + ДтКт + "3";
    
    // Внимание! Сигнатура вызова зависит от версии вашей БП 3.0 (см. раздел "Важные ловушки")
    БухгалтерскийУчетКлиентСервер.ПриВыбореСчета(СтрокаТаблицы["Счет" + ДтКт], Форма, ПоляФормы, Неопределено);
    
    ПоляОбъекта = Новый Структура("Субконто1,Субконто2,Субконто3,Подразделение,Валютный,Количественный,Организация");
    ПоляОбъекта.Субконто1      = "Субконто" + ДтКт + "1";
    ПоляОбъекта.Субконто2      = "Субконто" + ДтКт + "2";
    ПоляОбъекта.Субконто3      = "Субконто" + ДтКт + "3";
    ПоляОбъекта.Подразделение  = "Подразделение" + ДтКт;
    ПоляОбъекта.Валютный       = "Валютный" + ДтКт;
    ПоляОбъекта.Количественный = "Количественный" + ДтКт;
    ПоляОбъекта.Организация    = Форма.Объект.Организация;
    
    БухгалтерскийУчетКлиентСервер.ПриИзмененииСчета(СтрокаТаблицы["Счет" + ДтКт], СтрокаТаблицы, ПоляОбъекта, Истина, , Ложь);
    
КонецПроцедуры

На стороне сервера нам понадобятся легкие функции-помощники для быстрого получения ссылок на счета и элементы справочников:


&НаСервереБезКонтекста
Функция ПолучитьСчетПоКоду(КодСчета)
    Возврат ПланыСчетов.Хозрасчетный.НайтиПоКоду(КодСчета);
КонецФункции

&НаСервереБезКонтекста
Функция ПолучитьОрганизациюПоУмолчанию()
    // Здесь может быть ваша логика выбора организации
    Возврат Справочники.Организации.ПустаяСсылка(); 
КонецФункции

&НаСервереБезКонтекста
Функция ПолучитьНоменклатурнуюГруппу()
    // Пример получения конкретной номенклатурной группы для субконто
    Возврат Справочники.НоменклатурныеГруппы.НайтиПоНаименованию("Основная номенклатурная группа");
КонецФункции

&НаСервереБезКонтекста
Функция ПолучитьМатериал()
    // Пример получения элемента справочника Номенклатура
    Возврат Справочники.НоменклатурныеГруппы.ПустаяСсылка(); // Подставьте нужный справочник и поиск
КонецФункции

Важные ловушки и тонкости настройки

Проанализируем ключевые нюансы, несоблюдение которых может привести к ошибкам в работе программы или к потере целостности данных учета.

1. Изменение сигнатуры методов общего модуля в новых релизах БП 3.0.
Разработчики фирмы «1С» регулярно обновляют конфигурации, оптимизируя внутренний код. В старых релизах вызов метода БухгалтерскийУчетКлиентСервер.ПриВыбореСчета содержал шесть параметров. В современных версиях БП 3.0 (начиная с релизов 3.0.140 и более поздних) сигнатура метода сократилась. Последние два параметра булевого типа были удалены. Если вы напишете устаревший вариант вызова, система выдаст критическую ошибку времени выполнения: «Слишком много фактических параметров». Всегда используйте актуальный синтаксис, состоящий из четырех параметров. Для отслеживания актуальных параметров процедур и функций конфигурации пригодится справочник методов Бухгалтерии предприятия 3.0.

2. Обязательность заполнения служебных полей в строках движений.
Каждая добавляемая строка в коллекцию ХозрасчетныйНаборЗаписей обязательно должна содержать заполненные поля Период, Организация и Активность. Если поле Активность будет иметь значение Ложь (по умолчанию для новых строк в неуправляемом режиме), то после записи документа пользователем проводки физически запишутся, но не будут влиять на баланс организации и не попадут в Оборотно-сальдовую ведомость (ОСВ). Поле Период всегда должно совпадать с датой в шапке документа.

3. Динамическая природа субконто на управляемой форме.
Поскольку виды субконто определяются только после выбора конкретного счета учета, вы не можете обратиться к аналитике напрямую по имени, например, Строка.СубконтоДт.Номенклатура на клиенте. Платформа распределяет аналитику в плоскую структуру: СубконтоДт1, СубконтоДт2, СубконтоДт3. Порядок следования субконто жестко привязан к настройкам конкретного счета в Плане счетов «Хозрасчетный». Если вы сомневаетесь, под каким индексом идет нужное вам субконто, рекомендуем на сервере предварительно анализировать массив видов субконто счета.

Альтернативный вариант: Использование временного хранилища

Если логика заполнения документа слишком сложна, содержит тяжелые расчеты или вы не хотите использовать вызовы клиентских методов для заполнения счетов, можно применить альтернативный подход через временное хранилище:

  1. На сервере во внешней обработке соберите таблицу значений со всей информацией о будущих проводках.
  2. Поместите эту таблицу во временное хранилище платформы методом ПоместитьВоВременноеХранилище и получите уникальный адрес (строку).
  3. Передайте этот адрес в качестве параметра при открытии формы документа «Операция»:
    
    ПараметрыОткрытия = Новый Структура("АдресДанныхЗаполнения", АдресВХ);
    ОткрытьФорму("Документ.ОперацияБух.ФормаОбъекта", ПараметрыОткрытия);
    
  4. Чтобы этот параметр был обработан формой, вам потребуется использовать механизм Расширений конфигурации. В расширении необходимо перехватить процедуру формы ПриСозданииНаСервере или ОбработкаЗаполнения, считать переданную таблицу из хранилища и заполнить набор записей напрямую на стороне сервера до момента открытия формы на клиенте.

Такой подход считается более изящным с точки зрения архитектуры «1С», так как исключает интерактивное обращение к элементам формы и позволяет полностью подготовить данные на стороне сервера.

Мы подробно разобрали особенности работы с документом «Операция, введенная вручную» в конфигурациях на управляемых формах и научились программно подготавливать форму к заполнению. Используйте предложенные готовые шаблоны кода и учитывайте особенности платформы для создания надежных интеграционных решений!

← На главную