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