В процессе сопровождения информационных систем на базе 1С:Предприятие 7.7, особенно в конфигурации «Торговля и Склад» (ТиС), часто возникают ситуации, когда необходимо внести исправления в движения документов только по одному контуру учета. Например, вы обнаружили ошибку во взаиморасчетах с контрагентами, но при этом товарные остатки в базе верны, и полное перепроведение документов может привести к нежелательным изменениям в себестоимости или нарушению последовательности партионного учета. Рассмотрим подробнее, как можно реализовать механизм выборочного обновления движений.
Для начала проанализируем, как работает штатное проведение в «семерке». В отличие от версии 8.х, где за удаление движений обычно отвечает свойство метаданных, в 1С 7.7 (особенно в типовых конфигурациях) очистка движений часто прописывается явно в коде модуля документа. Разберем стандартный блок, который можно встретить в процедуре ОбработкаПроведения:
Процедура ПроведениеПоРегистрам()
// ...
// Удаление движений по регистрам.
Для Номер = 1 По Метаданные.Регистр() Цикл
ОчиститьДвижения("Регистр." + Метаданные.Регистр(Номер).Идентификатор);
КонецЦикла;
// ...
КонецПроцедуры
Этот код при каждом проведении полностью обнуляет записи документа во всех регистрах, за которыми он закреплен. Если мы хотим перепроводить только часть данных, нам необходимо вмешаться в этот алгоритм. Важно понимать: просто закомментировать очистку нельзя, иначе при повторном проведении новые записи добавятся к старым, что приведет к «удвоению» итогов.
Это наиболее корректный и гибкий метод с точки зрения программирования. Метод Провести() имеет необязательный второй параметр Знач, который передается напрямую в предопределенную процедуру ОбработкаПроведения модуля документа. Мы можем использовать этот параметр как флаг, указывающий системе, какой режим проведения использовать.
Рассмотрим по шагам реализацию этого метода:
ОбработкаПроведения добавим прием параметра.Пример модифицированного кода в модуле документа:
Процедура ОбработкаПроведения(ВидПроведения, ДопПараметр)
Если ДопПараметр = "ТолькоВзаиморасчеты" Тогда
// Очищаем только регистр взаиморасчетов
ОчиститьДвижения("Регистр.Покупатели");
// Вызываем только ту часть кода, которая пишет взаиморасчеты
ПровестиПоВзаиморасчетам();
Иначе
// Стандартное полное проведение
ОчиститьВсеДвижения();
ДвиженияПоВсемРегистрам();
КонецЕсли;
КонецПроцедуры
Теперь из внешней обработки мы можем вызвать перепроведение именно в этом режиме:
Док = СоздатьОбъект("Документ.Реализация");
Если Док.НайтиДокумент(НужныйДокумент) = 1 Тогда
Док.Провести(0, "ТолькоВзаиморасчеты");
КонецЕсли;
Если задача разовая и объемы данных не позволяют тратить время на архитектурные изменения конфигурации, можно прибегнуть к «административному» способу. Проанализируем последовательность действий:
ОбработкаПроведения временно комментируем вызовы процедур, отвечающих за формирование движений по регистрам товаров (например, регистр ОстаткиТМЦ или ПартииНаличие).ОчиститьДвижения() именно для этих «неприкосновенных» регистров.Внимание! При использовании этого метода необходимо обеспечить монопольный доступ к базе или быть уверенным, что в этот момент другие пользователи не проводят документы этого типа, иначе их данные также будут записаны некорректно.
Если ваша база работает на MS SQL Server, можно воспользоваться возможностями внешней компоненты 1С++. Этот путь предназначен для опытных разработчиков, так как он подразумевает прямую работу с таблицами базы данных, минуя объектную модель 1С.
Выясним причину, почему это эффективно: при обычном проведении 1С выполняет множество проверок, блокировок и транзакций. Прямой SQL-запрос UPDATE к таблице движений регистра (таблицы вида RA*) позволяет изменить суммы или аналитику во взаиморасчетах мгновенно. Однако помните о необходимости последующего пересчета итогов (таблицы RG*), так как 1С 7.7 хранит остатки отдельно от движений.
Проанализируем ситуацию с последовательностями. В 1С 7.7 любое перепроведение документа, даже частичное, может сдвинуть границу последовательности назад. Если вы изменили движения только по взаиморасчетам, но документ входит в последовательность «ПартионныйУчет», система пометит, что с этого момента последовательность не актуальна.
Чтобы избежать этой проблемы при массовом исправлении долгов, часто используют следующий алгоритм:
Последовательность.Посмотрим на пример кода для восстановления границы:
Посл = Последовательность.ОсновнаяПоследовательность;
Посл.Установить(ДатаГраницы, ДокГраницы);
Мы рассмотрели несколько подходов к решению задачи выборочного перепроведения. Самым надежным и рекомендуемым является Способ 1 с передачей флага в ОбработкаПроведения. Он позволяет сохранить логику конфигурации чистой и дает возможность автоматизировать процесс исправления ошибок без риска удаления важных данных в других регистрах. Всегда делайте резервную копию базы данных перед выполнением подобных операций, так как ошибки в работе с регистрами в 1С 7.7 могут потребовать полного пересчета итогов, что на больших базах занимает значительное время.