Иногда при работе с базой данных 1С:Предприятие 7.7 можно столкнуться с аномальным и, на первый взгляд, нелогичным поведением системы. Одна из таких ситуаций — когда запрос к регистру остатков возвращает данные по документам, которые не проведены. Это нарушает основную логику учета, ведь только проведенные документы должны формировать движения. Подобное поведение обычно свидетельствует о нарушении целостности данных в базе.
Рассмотрим на примере реальной ситуации, как диагностировать и исправить эту проблему.
Исходная проблема заключается в том, что простой запрос к регистру остатков в файловой базе 1С 7.7 неожиданно включает в результат непроведенные расходные накладные.
Процедура Сформировать()
Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса = "
|Период с ДатаС по ДатаПо;
|
|Товар = Регистр.Остатки.Товар;
|ТекДок = Регистр.Остатки.ТекущийДокумент;
|Кво = Регистр.Остатки.Кво;
|
|Функция КвоНач = НачОст(Кво);
|Функция КвоПрих = Приход(Кво);
|Функция КвоРасх = Расход(Кво);
|Функция КвоКон = КонОст(Кво);
|
|Группировка ТекДок;
|
|Условие(Товар = выбТовар);
|";
Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
Возврат;
КонецЕсли;
Запрос.Выгрузить(тз, 0, 0);
КонецПроцедуры
Стандартные процедуры, такие как переиндексация и "Тестирование и исправление" (ТиИ), в данном случае не помогают. Разберемся, в чем причина и как действовать.
Первое, что нужно сделать, — это убедиться, что у непроведенного документа действительно есть записи (движения) в таблице регистра. Запрос может получать данные только в том случае, если они физически существуют. Выполним программную проверку.
Для этого можно использовать метод ВыбратьДвиженияДокумента() объекта Регистр. Этот код позволяет перебрать все движения, связанные с конкретным документом.
// Предполагается, что в переменной "Док" находится ссылка
// на "проблемный" непроведенный документ
Рег = СоздатьОбъект("Регистр.Остатки");
Рег.ВыбратьДвиженияДокумента(Док);
Пока Рег.ПолучитьДвижение() = 1 Цикл
Сообщить("Обнаружено движение: " + Рег.Товар + ", Кво " + Рег.Кво);
КонецЦикла;
Если этот код выводит сообщения, значит, диагноз подтвержден: в базе данных существуют "фантомные" движения, привязанные к непроведенному документу. Такие движения не должны существовать, и их наличие указывает на сбой.
Откуда могли появиться такие "осиротевшие" движения? Причин может быть несколько:
1SJOURN.DBF), оставив при этом связанные движения в таблицах регистров (RA*.DBF, RG*.DBF) нетронутыми.Существует несколько подходов к решению этой проблемы, от щадящих до радикальных. Рекомендуем двигаться по порядку.
Стандартный способ "вылечить" такой документ — это провести его и сразу же отменить проведение. При отмене проведения штатный механизм 1С должен корректно удалить все связанные с ним движения.
Проблема: Часто такой документ невозможно провести, так как он сам же и списал остатки, которых теперь не хватает для его проведения. Система выдаст ошибку "Недостаточно товара".
Обходной путь:
ОбработкаПроведения() в модуле "проблемного" документа.Возврат;. Это отключит все проверки, включая контроль остатков.
Процедура ОбработкаПроведения()
// Весь старый код закомментирован
// ...
Возврат;
КонецПроцедуры
ОбработкаПроведения().Важно: Этот способ может не сработать, если в конфигурации (например, в типовой "Торговля и Склад") отключено автоматическое удаление движений при отмене проведения. В таком случае переходим к следующему решению.
Этот метод является наиболее надежным, но требует повышенной осторожности и понимания структуры данных 1С. Он заключается в ручном удалении записей из файлов базы данных.
ШАГ 0. ОБЯЗАТЕЛЬНО СДЕЛАЙТЕ РЕЗЕРВНУЮ КОПИЮ БАЗЫ ДАННЫХ!
// Требуется компонента MetaDataWork
Метадата = СоздатьОбъект("MetaDataWork");
// В переменной ТвойДок - ссылка на нужный документ
Сообщить(Метадата.ЗначениеВСтрокуБД(ТвойДок));
' 44DL ', которая и является искомым ID.
ЗначениеВСтрокуВнутр(). Этот способ не требует внешних компонент, но сложнее, так как результат нужно парсить.
// В переменной ТвойДок - ссылка на нужный документ
ВнутрПредставление = ЗначениеВСтрокуВнутр(ТвойДок);
// Результат будет вида: {"O", ... ," 5136 192297 "}
// Из этой строки нужно извлечь и преобразовать ID.
RA[НомерРегистра].DBF (для регистров остатков) и RG[НомерРегистра].DBF (для регистров оборотов). В обсуждаемом примере это был файл RA45.DBF.WinDBFView.exe, DBF Navigator или плагина в Total Commander.После выполнения этих шагов "фантомные" движения будут удалены, и запрос начнет работать корректно, не показывая непроведенные документы.
В ходе обсуждения также был затронут вопрос о разнице между двумя вариантами группировки в запросе:
Вариант 1 (как в исходном коде):
|ТекДок = Регистр.Остатки.ТекущийДокумент;
|Группировка ТекДок;
Вариант 2 (предопределенная группировка):
|Группировка Документ;
Хотя результат в большинстве случаев будет идентичным, использование предопределенной группировки Документ считается более правильным и потенциально более быстрым, так как система использует для этого оптимизированный механизм.