При программном создании расчетных документов в платформе 1С:Предприятие разработчики нередко сталкиваются с ситуацией, когда документ успешно создается, реквизиты шапки заполнены, но при попытке записи возникает ошибка: «Сумма по документу и сумма в расшифровке не совпадают». При этом отладчик показывает, что блок кода с заполнением строк табличной части просто пропускается. Разберем по шагам, почему возникает эта ошибка и как правильно заполнять табличные части при создании новых документов.
Посмотрим на фрагмент исходного кода, где создается новый документ ОплатаПлатежнойКартой:
ДокОПК = Документы.ОплатаПлатежнойКартой.СоздатьДокумент();
ДокОПК.ВидОперации = Объект.ВидОперации;
ДокОПК.Контрагент = Склад;
ДокОПК.Дата = ДатаОПК;
ДокОПК.ВидОплаты = Объект.ВидОплаты;
ДокОПК.СуммаДокумента = СуммаОПК;
ДокОПК.СтавкаНДС = Перечисления.СтавкиНДС.БезНДС;
ДокОПК.Организация = Справочники.Организации.НайтиПоКоду("00-000002");
ДокОПК.Комментарий = Склад.Наименование;
Для каждого Расшифровка Из ДокОПК.РасшифровкаПлатежа Цикл
Расшифровка.СпособПогашенияЗадолженности = Перечисления.СпособыПогашенияЗадолженности.Автоматически;
Расшифровка.СуммаПлатежа = ДокОПК.СуммаДокумента;
Расшифровка.КурсВзаиморасчетов = 1;
Расшифровка.СуммаВзаиморасчетов = Расшифровка.СуммаПлатежа;
Расшифровка.КратностьВзаиморасчетов = 1;
КонецЦикла;
ДокОПК.Записать(РежимЗаписиДокумента.Запись);
Проанализируем ситуацию: метод Документы.ОплатаПлатежнойКартой.СоздатьДокумент() создает в оперативной памяти абсолютно новый, пустой экземпляр документа. В только что созданном объекте табличная часть РасшифровкаПлатежа не содержит ни одной строки — ее количество элементов равно нулю.
Конструкция Для каждого Расшифровка Из ДокОПК.РасшифровкаПлатежа Цикл предназначена исключительно для обхода уже существующих строк коллекции. Поскольку строк в табличной части нет, платформе не по чему итерироваться: цикл завершается сразу же, тело цикла не выполняется ни разу, и ни одна строка с суммой так и не создается. В результате реквизит СуммаДокумента заполнен значением, а сумма по строкам пустой табличной части равна 0, что и вызывает отказ типовой проверки перед записью.
Для создания новых строк в табличных частях объектов 1С используется метод коллекции Добавить(). Этот метод создает новую строку в табличной части и возвращает ссылку на нее, после чего можно приступать к заполнению реквизитов.
Заменим ошибочный цикл на явное добавление строки:
// Добавляем новую строку в табличную часть
СтрокаРасшифровки = ДокОПК.РасшифровкаПлатежа.Добавить();
СтрокаРасшифровки.СпособПогашенияЗадолженности = Перечисления.СпособыПогашенияЗадолженности.Автоматически;
СтрокаРасшифровки.СуммаПлатежа = ДокОПК.СуммаДокумента;
СтрокаРасшифровки.КурсВзаиморасчетов = 1;
СтрокаРасшифровки.СуммаВзаиморасчетов = СтрокаРасшифровки.СуммаПлатежа;
СтрокаРасшифровки.КратностьВзаиморасчетов = 1;
После добавления строки табличная часть перестает быть пустой, и равенство сумм восстанавливается.
Рассмотрим подробнее другие моменты представленного кода, которые могут привести к критическим ошибкам при проведении документа или искажению данных бухгалтерского учета:
ДокОПК.Контрагент = Склад; переменная имеет имя Склад. Если в эту переменную помещена ссылка на справочник Склады, то в реквизит Контрагент запишется пустая ссылка или произойдет ошибка несовпадения типов, так как данный реквизит ожидает тип СправочникСсылка.Контрагенты. Необходимо следить за передачей корректных ссылок.
РасшифровкаПлатежа обязательно должны быть заполнены аналитики:
ДоговорКонтрагента — ключевой разрез учета расчетов с контрагентом. Без договора механизмы проведения конфигурации вернут ошибку валюты расчетов или признака расчетов в условных единицах.СчетУчетаРасчетовСКонтрагентом и СчетУчетаРасчетовПоАвансам — счета расчетов (обычно 62.01 и 62.02). При программном заполнении их следует получать и прописывать явно, например, из регистра сведений счетов расчетов по умолчанию.СтатьяДДС — статья движения денежных средств, необходимая для формирования регламентированных проводок.КурсВзаиморасчетов = 1 и КратностьВзаиморасчетов = 1 допустима только в том случае, если взаиморасчеты ведутся строго в валюте регламентированного учета (рублях). Если договор оформлен в валюте или у.е., курс и кратность необходимо получать из регистра сведений «Курсы валют» на дату документа и корректно рассчитывать СуммаВзаиморасчетов.
ДокОПК.Заполнить(Неопределено). Это позволит автоматически заполнить системные реквизиты (организацию по умолчанию, ответственного, подразделение) согласно настройкам текущей информационной базы, сократив количество ручного кода.
С учетом всех разобранных правил соберем правильный вариант формирования документа оплаты картой:
ДокОПК = Документы.ОплатаПлатежнойКартой.СоздатьДокумент();
// Первичная инициализация типовых реквизитов значениями по умолчанию
ДокОПК.Заполнить(Неопределено);
// Заполнение шапки документа
ДокОПК.ВидОперации = Объект.ВидОперации;
ДокОПК.Организация = Справочники.Организации.НайтиПоКоду("00-000002");
ДокОПК.Дата = ДатаОПК;
ДокОПК.Контрагент = КонтрагентСсылка; // Передаем ссылку на справочник Контрагенты
ДокОПК.ВидОплаты = Объект.ВидОплаты;
ДокОПК.СуммаДокумента = СуммаОПК;
ДокОПК.СтавкаНДС = Перечисления.СтавкиНДС.БезНДС;
ДокОПК.Комментарий = "Создано программно";
// Формирование строки табличной части
СтрокаРасшифровки = ДокОПК.РасшифровкаПлатежа.Добавить();
СтрокаРасшифровки.ДоговорКонтрагента = ДоговорСсылка;
СтрокаРасшифровки.СпособПогашенияЗадолженности = Перечисления.СпособыПогашенияЗадолженности.Автоматически;
СтрокаРасшифровки.СуммаПлатежа = ДокОПК.СуммаДокумента;
СтрокаРасшифровки.КурсВзаиморасчетов = 1;
СтрокаРасшифровки.КратностьВзаиморасчетов = 1;
СтрокаРасшифровки.СуммаВзаиморасчетов = ДокОПК.СуммаДокумента;
// Заполнение счетов учета расчетов
СтрокаРасшифровки.СчетУчетаРасчетовСКонтрагентом = ПланыСчетов.Хозрасчетный.РасчетыСПокупателями; // 62.01
СтрокаРасшифровки.СчетУчетаРасчетовПоАвансам = ПланыСчетов.Хозрасчетный.РасчетыПоАвансамПолученным; // 62.02
// Безопасная запись объекта
Попытка
ДокОПК.Записать(РежимЗаписиДокумента.Запись);
Исключение
ВызватьИсключение "Ошибка при сохранении документа: " + ОписаниеОшибки();
КонецПопытки;
Использование метода Добавить() вместо попытки перебора пустой таблицы исключает ошибку расхождения сумм и гарантирует корректную запись нового документа.