Почему помеченный на удаление документ в 1С 7.7 сохраняет движения и как это исправить?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

В процессе администрирования и сопровождения баз данных на платформе 1С:Предприятие 7.7 специалисты иногда сталкиваются с крайне неприятной аномалией: документ, который визуально помечен на удаление (перечеркнут крестиком в журнале), продолжает делать движения по регистрам оперативного учета или формировать бухгалтерские проводки. В результате этого искажаются отчеты, разъезжаются остатки на складах и взаиморасчеты с контрагентами.

В этой статье мы подробно разберем, почему возникает подобная рассинхронизация на физическом уровне базы данных, проанализируем основные причины сбоя для SQL- и DBF-версий, а также рассмотрим пошаговые инструкции и примеры программного кода для автоматического исправления таких ошибок.

Как устроено хранение данных в 1С 7.7 «под капотом»

Чтобы понять природу этой проблемы, давайте проанализируем, каким образом платформа 1С 7.7 организует хранение информации в СУБД. В отличие от современных версий платформы, где объектная модель жестко контролирует ссылочную целостность, в «семерке» связь между документами и их движениями более хрупкая.

Данные о документах и их движениях физически разделены по разным таблицам:

  1. Общий журнал документов: Вся ключевая информация о состоянии документа (дата, время, номер, вид документа, его статус) хранится в таблице _1SJOURN (для SQL-версий) или в файле 1SJOURN.DBF (для файловых версий). За статус проведения отвечает колонка CLOSED, а за пометку на удаление — колонка ISMARK.
  2. Таблицы движений регистров: Движения по регистрам оперативного учета записываются в отдельные таблицы с префиксом RA (например, RA325, где число — это внутренний идентификатор регистра в метаданных).
  3. Таблица бухгалтерских проводок: Все проводки хранятся в единой физической таблице _1SENTRY (или 1SENTRY.DBF).

В штатном режиме работы, когда пользователь помечает документ на удаление, платформа 1С 7.7 открывает транзакцию и выполняет комплексное действие: меняет значение флага ISMARK на 1 в таблице журнала и одновременно очищает записи с соответствующим IDDOC (идентификатором документа) во всех подчиненных таблицах движений (RA* и _1SENTRY). Если этот процесс нарушается, возникает рассинхронизация.

Выясняем причины появления «фантомных» движений

Рассмотрим основные сценарии, при которых транзакция очистки движений может завершиться некорректно или вообще не запуститься.

1. Аварийное завершение работы в момент транзакции

Если в процессе отмены проведения или пометки документа на удаление на компьютере пользователя происходит критический сбой (например, аварийно закрывается процесс 1cv7s.exe, отключается электропитание, зависает сессия на терминальном сервере или пропадает сетевое соединение с SQL-сервером), транзакция может записаться частично. База данных успевает зафиксировать статус пометки удаления в таблице журнала, но соединение разрывается до того, как СУБД успевает физически удалить строки из таблиц движений.

2. Нарушение целостности индексов в DBF-базах

В файловых версиях баз данных транзакционность поддерживается на программном уровне самой платформы. Если база аварийно завершила работу, индексные файлы (с расширением .CDX) могут потерять синхронизацию с физическими файлами таблиц (.DBF). При повреждении индексов платформа при чтении журнала может считывать одну информацию, а при обращении к регистрам — физически находить записи движений, которые должны были быть удалены.

3. Прямое манипулирование данными (Direct SQL или DBF-редакторы)

Очень часто программисты используют прямые запросы к базе данных через внешние компоненты (например, 1С++) или сторонний софт для ускорения групповых операций (например, при свертке информационной базы). Если разработчик написал запрос обновления статуса в таблице _1SJOURN напрямую:

UPDATE _1SJOURN SET ISMARK = 1, CLOSED = 0 WHERE IDDOC = ' 1Y7 ';

Но при этом забыл написать сопутствующие запросы на удаление движений из всех таблиц регистров RA*, документ визуально станет помеченным на удаление, но фактически продолжит влиять на остатки.

4. Ошибки при обмене данными через УРБД

При использовании распределенных информационных баз (УРБД) изменения мигрируют между периферийными базами и центром. Если в правилах миграции допущены логические ошибки или во время обмена произошел сбой чтения XML/ID-файла переноса, документ может получить статус «Помечен на удаление» в одной из баз, но пакет с удалением его движений не будет применен.

5. Отключение свойства «Автоматическое удаление движений»

В свойствах конфигурации каждого документа есть флаг «Автоматическое удаление движений». Если эта галочка снята, то вся ответственность за очистку регистров ложится на плечи разработчика. В этом случае в модуле документа должна быть прописана процедура ручной очистки. Если в коде перед очисткой движений стоит жесткий оператор Возврат или возникает необработанное исключение, то документ изменит статус, но его движения останутся нетронутыми.

Как обнаружить проблемные документы программным путем

Давайте разберем, как написать простую и эффективную обработку на встроенном языке 1С 7.7, которая позволит обойти всю базу данных и выявить документы, помеченные на удаление, но имеющие физические движения по какому-либо регистру.

Для примера рассмотрим поиск зависших движений по регистру оперативного учета ОстаткиТоваров:


Процедура НайтиОшибкиРегистра()
    Док = СоздатьОбъект("Документ");
    Рег = СоздатьОбъект("Регистр.ОстаткиТоваров");
    
    // Выбираем все документы в базе данных
    Док.ВыбратьДокументы();
    Пока Док.ПолучитьДокумент() = 1 Цикл
        // Проверяем, установлен ли флаг пометки удаления
        Если Док.ПометкаУдаления() = 1 Тогда
            // Проверяем, есть ли движения по нашему регистру для этого документа
            Рег.ВыбратьДвиженияДокумента(Док.ТекущийДокумент());
            Если Рег.ПолучитьДвижение() = 1 Тогда
                Сообщить("Найдена ошибка! Документ " + Док.ТекущийДокумент() + " (" + Док.Вид() + ") помечен на удаление, но сохранил движения!");
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Этот простой алгоритм поможет нам локализовать масштаб проблемы и понять, какие именно виды документов пострадали в результате сбоя.

Пошаговая инструкция по исправлению базы данных

Проанализируем методы исправления этой ситуации. В зависимости от масштаба базы и причин возникновения сбоя, мы можем применить несколько подходов.

Способ 1. Тестирование и исправление информационной базы (ТиИ)

Это самый надежный и штатный способ исправления логической целостности базы данных. Перед выполнением процедуры обязательно сделайте резервную копию базы данных!

  1. Запустите конфигуратор 1С:Предприятия 7.7 в монопольном режиме.
  2. Перейдите в меню «Администрирование» -> «Тестирование и исправление ИБ».
  3. Установите галочки напротив пунктов:
    • «Реиндексация таблиц» (особенно актуально для DBF-версий);
    • «Проверка физической целостности»;
    • «Проверка логической целостности»;
    • «Пересчет итогов».
  4. В окне настроек обработки неопределенных объектов выберите опцию «Удалять» или «Очищать ссылки».
  5. Нажмите кнопку «Выполнить».

В процессе логической проверки платформа самостоятельно сопоставит таблицы заголовков документов с таблицами движений и удалит все «осиротевшие» записи из регистров.

Способ 2. Программное исправление через вызов штатных методов

Если повреждения носят локальный характер, мы можем программно заставить платформу корректно перезаписать статус документа. При вызове штатных методов интерактивной пометки удаления 1С 7.7 автоматически инициирует правильную транзакцию и очищает регистры.

Напишем небольшую обработку, которая автоматически снимет пометку удаления и установит ее заново для всех некорректных документов:


Процедура ИсправитьДокументы()
    Док = СоздатьОбъект("Документ");
    Рег = СоздатьОбъект("Регистр.ОстаткиТоваров"); // Укажите ваш проблемный регистр
    
    Док.ВыбратьДокументы();
    Пока Док.ПолучитьДокумент() = 1 Цикл
        Если Док.ПометкаУдаления() = 1 Тогда
            Рег.ВыбратьДвиженияДокумента(Док.ТекущийДокумент());
            Если Рег.ПолучитьДвижение() = 1 Тогда
                Сообщить("Исправляем документ: " + Док.ТекущийДокумент());
                
                // Открываем транзакцию для безопасности
                НачатьТранзакцию();
                
                // Снимаем пометку удаления (документ временно становится просто записанным)
                Док.СнятьПометкуУдаления();
                
                // Повторно устанавливаем пометку удаления. 
                // Этот метод заставит платформу принудительно очистить таблицы движений.
                Док.УстановитьПометкуУдаления();
                
                ЗафиксироватьТранзакцию();
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
    Сообщить("Процесс исправления успешно завершен!");
КонецПроцедуры

Важное примечание: Использование транзакции (НачатьТранзакцию() и ЗафиксироватьТранзакцию()) гарантирует, что если в процессе изменения одного из документов произойдет непредвиденная блокировка или сбой, система откатит изменения к исходному состоянию, предотвратив еще большую рассинхронизацию.

Способ 3. Прямая очистка через SQL-запрос (для клиент-серверных баз)

Если ваша база работает под управлением MS SQL Server и объем данных настолько велик, что штатное тестирование и исправление занимает слишком много времени, администратор базы данных может выполнить очистку напрямую через SQL Server Management Studio (SSMS).

Перед выполнением этого шага необходимо сопоставить идентификаторы метаданных из файла 1cv7.dd с физическими именами таблиц в SQL. Предположим, что таблица регистра остатков называется _1SENTRY (для проводок) или RA325 (для регистра).

Для очистки зависших бухгалтерских проводок по документам, помеченным на удаление, мы можем использовать следующий SQL-запрос:


-- Удаляем проводки из таблицы _1SENTRY, если документ в журнале _1SJOURN помечен на удаление
DELETE FROM _1SENTRY
WHERE IDDOC IN (
    SELECT IDDOC 
    FROM _1SJOURN 
    WHERE ISMARK = 1
);

Аналогичным образом мы можем поступить с движениями конкретного регистра накопления:


-- Удаляем движения регистра RA325 по помеченным на удаление документам
DELETE FROM RA325
WHERE IDDOC IN (
    SELECT IDDOC 
    FROM _1SJOURN 
    WHERE ISMARK = 1
);

После выполнения таких SQL-запросов в обязательном порядке необходимо запустить конфигуратор 1С и выполнить процедуру «Пересчет итогов», чтобы СУБД пересчитала актуальные остатки в таблицах итогов (таблицы с префиксом RG*), иначе остатки в отчетах по-прежнему будут неверными.

Рекомендации по предотвращению подобных сбоев

Чтобы минимизировать риски повторного появления документов-призраков с активными движениями, рекомендуем придерживаться следующих правил администрирования:

Мы подробно проанализировали причины сбоя, структуру хранения данных в 1С 7.7 и рассмотрели практические варианты решения проблемы. Применяя данные методики, вы сможете быстро вернуть базу данных в консистентное состояние и обеспечить точность ведения учета.

← На главную