При разработке обработок загрузки данных из внешних XML-файлов часто возникает ситуация, когда при повторном запуске процедуры один и тот же файл считывается заново, создавая дублирующие документы ПоступлениеТоваровУслуг и подчиненные счета-фактуры. Разберем, как правильно реализовать проверку наличия ранее созданных документов в базе данных 1С и исключить их дублирование.
Самый простой способ избежать создания дублей — выполнить поиск ссылки на существующий документ по номеру входящего документа перед созданием нового объекта. Метод менеджера документа НайтиПоРеквизиту позволяет получить ссылку на документ, у которого реквизит совпадает с переданным значением.
Посмотрим на пример встраивания проверки в цикл обработки после чтения XML:
// После прочтения переменных из XML (аа - номер входящего документа)
НайденныйДок = Документы.ПоступлениеТоваровУслуг.НайтиПоРеквизиту("НомерВходящегоДокумента", аа);
Если Не НайденныйДок.Пустая() Тогда
Сообщить("Документ с входящим номером " + аа + " уже существует в базе! Пропускаем.");
Продолжить;
КонецЕсли;
// Далее следует стандартный код создания и проведения документа
ДокОбъект = Документы.ПоступлениеТоваровУслуг.СоздатьДокумент();
// ...
Важное ограничение: метод НайтиПоРеквизиту ищет только по одному полю и возвращает первый попавшийся документ во всей базе. Если у двух разных контрагентов совпадают номера документов (например, номер «1»), программа ошибочно пропустит загрузку. Поэтому такой способ подходит только для простых задач с гарантированно уникальной нумерацией.
Проанализируем более надежный и правильный подход. В реальном учете уникальность входящего документа определяется совокупностью нескольких параметров:
Разберем, как выполнить поиск существующего поступления с помощью запроса внутри цикла обработки:
КонтрагентПоступления = Справочники.Контрагенты.НайтиПоКоду("УT0000063");
ОрганизацияПоступления = Справочники.Организации.НайтиПоКоду("000000001");
ДатаВх = Дата(вв);
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Поступление.Ссылка КАК Ссылка
|ИЗ
| Документ.ПоступлениеТоваровУслуг КАК Поступление
|ГДЕ
| Поступление.Проведен = ИСТИНА
| И Поступление.Организация = &Организация
| И Поступление.Контрагент = &Контрагент
| И Поступление.НомерВходящегоДокумента = &НомерВходящегоДокумента
| И Поступление.ДатаВходящегоДокумента = &ДатаВходящегоДокумента";
Запрос.УстановитьПараметр("Организация", ОрганизацияПоступления);
Запрос.УстановитьПараметр("Контрагент", КонтрагентПоступления);
Запрос.УстановитьПараметр("НомерВходящегоДокумента", СокрЛП(аа));
Запрос.УстановитьПараметр("ДатаВходящегоДокумента", НачалоДня(ДатаВх));
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
Выборка = РезультатЗапроса.Выбрать();
Выборка.Следующий();
Сообщить("Документ по накладной № " + аа + " от " + Формат(ДатаВх, "ДФ=dd.MM.yyyy") + " уже загружен: " + Строка(Выборка.Ссылка));
Продолжить;
КонецЕсли;
Если файлов много, выполнение запроса в цикле по каждому файлу замедляет работу. Рассмотрим архитектурно более эффективный способ: предварительный сбор данных из всех файлов с последующей проверкой одним общим запросом.
ТаблицаЗначений.Документ.ПоступлениеТоваровУслуг.Выясним важные нюансы, которые необходимо учесть при автоматическом создании поступлений и счетов-фактур:
ПоступлениеТоваровУслуг и создание подчиненного СчетФактураПолученный должны выполняться внутри явной транзакции (НачатьТранзакцию() / ЗафиксироватьТранзакцию()). Если при создании счета-фактуры произойдет сбой, транзакция отменится через блок Исключение, что предотвратит появление «оторванных» документов без счетов-фактур.ДокументыОснования документа СчетФактураПолученный, чтобы не создавать несколько счетов-фактур на одно поступление.ПереместитьФайл() или переименовывать. Это исключит повторную обработку старых файлов при следующих запусках.