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