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