
В предыдущей статье https://habr.com/ru/articles/1080394/ было описано, как массово находить документы за выбранный период, отменять их проведение и помечать на удаление. Это распространенная задача, а штатных средств для ее решения в программе нет. Мной была создана внешняя обработка, которая в несколько проходов последовательно удаляет доступные ей зависимости между документами, отменяет их проведение и устанавливает пометки удаления.
Однако при испытании обработки на базе с документами производства выяснилось, что существует отдельная группа объектов, с которой такой универсальный алгоритм не справляется. Проблемы возникли с завершенными этапами, производственными операциями, сменными заданиями, а при ремонтах — с отраженными в этапах расходах материалов и работ.
Документы оказались накрепко связаны между собой в замкнутые цепочки: один документ не желает меняться, пока не изменится второй, а второй — пока не изменится первый. Для разрыва таких цепочек понадобилась еще одна — «Производственная обработка».
Алгоритм «Производственной обработки»
Код обработки решает четыре задачи:
Подготовка сменных заданий. Обработка находит сменные задания за выбранный период, находящиеся в закрытом состоянии. Такие задания сначала переводятся из состояния Закрыто в состояние Сформировано. Это необходимо, чтобы снять ограничения, связанные с завершенными сменными заданиями, и подготовить связанные производственные объекты к дальнейшей обработке.
Подготовка этапов производства и устранение связанных с ними материальных зависимостей. У каждого найденного этапа очищается табличная часть РасходМатериаловИРабот, после чего этап штатными средствами конфигурации переводится из состояния Завершен в состояние Начат. Простого изменения реквизита
Статуснедостаточно: обработка вызывает стандартную логику 1С:ERP изменения статуса и затем записывает документ с проведением. В результате этап отображается в системе как Начат, Ожидает завершения.Установка пометки удаления производственным операциям. После подготовки этапов обработка находит относящиеся к производству операции и пытается установить для них стандартную пометку удаления. Непосредственного удаления объектов из информационной базы не производится. Если штатные проверки 1С:ERP не позволяют пометить конкретную операцию на удаление, объект остается без изменения, а ошибка фиксируется для диагностики.
Подготовка сменных заданий к удалению. После обработки этапов и производственных операций обработка повторно ищет за выбранный период все сменные задания, находящиеся в состоянии Сформировано. При этом не имеет значения, были они переведены в это состояние текущим запуском обработки или находились в нем ранее. Найденные задания штатными средствами 1С:ERP переводятся в состояние Формируется, после чего им устанавливается стандартная пометка удаления. Если какое‑либо задание не удается изменить с первого раза, обработка повторяет попытку в следующем проходе.
Для каждого действия ведется статистика: количество найденных и измененных сменных заданий, найденных и измененных этапов производства, удаленных строк расхода материалов и работ, найденных производственных операций, установленных пометок удаления и возникших ошибок.
Таким образом, «Производственная обработка» сама не выполняет физического удаления объектов из информационной базы. Ее задача — изменить состояние специфических производственных объектов и устранить блокировки, из‑за которых универсальная обработка не может последовательно удалить существующие между документами зависимости.
После работы «производственной обработки» «универсальная обработка» запускается повторно: она в несколько проходов отменяет проведение оставшихся документов и устанавливает им пометки удаления.
Теперь рассмотрим, как устроена внешняя обработка, реализующая этот алгоритм.
Форма и код «производственной обработки»
Для работы обработке необходимо получить от пользователя только период, за который требуется найти связанные с производством объекты. Поэтому на форме достаточно двух реквизитов:
НачалоПериода — дата начала периода;
КонецПериода — дата окончания периода.
Для контроля результатов на форме предусмотрены две таблицы: ПроизводственныеОперации и ЭтапыПроизводства.
В таблице ПроизводственныеОперации для каждой найденной операции отображаются сама операция, связанный с ней этап производства, номер, статус, наличие пометки удаления, результат обработки и текст возникшей ошибки.
В таблице ЭтапыПроизводства отображаются найденный этап, его дата и номер, исходный статус, результат обработки и текст ошибки.
Таким образом, таблицы выполняют роль пообъектного протокола обработки. Итоговая статистика показывает общий результат выполнения команды, а таблицы позволяют увидеть, что именно произошло с каждым найденным этапом и каждой производственной операцией, и при необходимости определить объект, на котором возникла ошибка.
Результаты обработки сменных заданий в отдельную таблицу не выводятся: для них в текущем варианте обработки используется итоговая статистика.

На форме нужна одна основная команда — Обработать.

После ее выполнения обработка последовательно выполняет несколько частей алгоритма.
Сначала она ищет за выбранный период закрытые сменные задания. Найденные сменные задания переводятся из состояния Закрыто в Сформировано. Это позволяет снять ограничения, связанные с закрытыми сменными заданиями, и продолжить подготовку производственных объектов к удалению.
Затем обработка ищет за выбранный период завершенные этапы производства. У каждого найденного этапа очищается табличная часть РасходМатериаловИРабот, после чего вызывается штатная логика 1С:ERP изменения статуса и документ записывается с проведением. Если операция выполнена успешно, этап переходит из состояния Завершен в Начат, Ожидает завершения. Если система не разрешает изменение, этап остается без изменения, а ошибка фиксируется в результатах работы.
После обработки этапов выполняется поиск производственных операций. Для каждой найденной операции обработка пытается установить стандартную пометку удаления. Если штатные проверки 1С:ERP разрешают это действие, операция помечается на удаление. Если нет — объект остается без изменения, а сообщение об ошибке сохраняется для диагностики.
На заключительном этапе обработка повторно ищет за выбранный период все сменные задания в состоянии Сформировано, независимо от того, были они переведены в это состояние текущим запуском обработки или находились в нем ранее. Найденные задания штатными средствами 1С:ERP переводятся в состояние Формируется, после чего им устанавливается стандартная пометка удаления. Если какое‑либо задание не удается обработать с первого раза, попытка повторяется в следующем проходе.
По окончании пользователю выводится итоговая статистика:
найдено сменных заданий;
переведено сменных заданий из состояния Закрыто в Сформировано;
возвращено сменных заданий в состояние Формируется;
помечено сменных заданий на удаление;
найдено завершенных этапов;
изменено этапов;
очищено этапов с расходом материалов и работ;
удалено строк из табличной части РасходМатериаловИРабот;
найдено производственных операций;
помечено операций на удаление;
количество ошибок.
Таким образом, форма обработки остается достаточно простой. Пользователю не требуется вручную выбирать отдельные сменные задания, этапы и операции или определять порядок их обработки. Он задает период и запускает команду Обработать. Обработка сама выполняет предусмотренную последовательность действий, выводит итоговую статистику и формирует пообъектный протокол обработки этапов производства и производственных операций.
При этом обработка не выполняет физического удаления производственных документов. Она изменяет состояние специфических объектов производственного контура и устраняет блокировки, мешающие работе «Универсальной обработки». После ее выполнения «Универсальная обработка» запускается повторно и продолжает отмену проведения и установку пометок удаления для оставшихся документов.
Далее приведен код обработки, а в конце статьи рассмотрена полная последовательность массового удаления документов: первый запуск «Универсальной обработки» → «Производственная обработка» → повторный запуск «Универсальной обработки» → штатные механизмы 1С:ERP.
// ВНЕШНЯЯ ОБРАБОТКА // Подготовка производственных документов к удалению. // // Назначение обработки: // // 1. Найти сменные задания за выбранный период. // 2. Закрытые сменные задания штатным механизмом ERP // перевести из статуса "Закрыто" в статус "Сформировано". // Это снимает блокировку изменения производственных операций, // принадлежащих закрытым сменным заданиям. // // 3. Найти этапы производства за выбранный период. // 4. У завершенных этапов полностью очистить табличную часть // "РасходМатериаловИРабот". Это снимает отраженный в этапе // расход материалов перед последующим удалением документов. // 5. Этапы со статусом "Завершен" штатно перевести в статус "Начат". // 6. Перепровести измененные этапы. // В испытанной базе после проведения ERP переводила этапы // в состояние "Начат, Ожидает завершения". // // 7. Найти производственные операции за выбранный период. // 8. Пометить производственные операции на удаление. // // 9. Повторно найти за период все сменные задания в состоянии // "Сформировано" и штатным механизмом ERP многопроходно // перевести их из "Сформировано" в "Формируется". // 10. После успешного перехода установить сменным заданиям // стандартную пометку удаления. // // После выполнения этой обработки можно запускать основную обработку V3, // которая многопроходно отменяет проведение остальных документов // и устанавливает им пометки удаления. &НаКлиенте Процедура ИзменитьСтатусы(Команда) // Начало периода обязательно. Если НЕ ЗначениеЗаполнено(НачалоПериода) Тогда Сообщить("Не указано начало периода."); Возврат; КонецЕсли; // Конец периода также обязателен. Если НЕ ЗначениеЗаполнено(КонецПериода) Тогда Сообщить("Не указан конец периода."); Возврат; КонецЕсли; // Проверяем корректность диапазона дат. Если НачалоПериода > КонецПериода Тогда Сообщить("Начало периода не может быть больше конца периода."); Возврат; КонецЕсли; // Вся фактическая работа с документами выполняется на сервере. Результат = ИзменитьСтатусыНаСервере(); // Выводим итоговую статистику. Сообщить( "Сменных заданий найдено: " + Строка(Результат.СменныхЗаданийНайдено) + ". Из ""Закрыто"" в ""Сформировано"": " + Строка(Результат.СменныхЗаданийСформировано) + ". Этапов найдено: " + Строка(Результат.Найдено) + ". Завершенных: " + Строка(Результат.Завершенных) + ". Очищен расход у этапов: " + Строка(Результат.ЭтаповСОчищеннымРасходом) + ". Удалено строк расхода: " + Строка(Результат.СтрокРасходаУдалено) + ". Переведено в ""Начат"": " + Строка(Результат.Изменено) + ". Операций найдено: " + Строка(Результат.ОперацийНайдено) + ". Операций помечено на удаление: " + Строка(Результат.ОперацийПомечено) + ". Сменных заданий возвращено в ""Формируется"": " + Строка(Результат.СменныхЗаданийФормируется) + ". Сменных заданий помечено на удаление: " + Строка(Результат.СменныхЗаданийПомечено) + ". Ошибок: " + Строка(Результат.Ошибок)); КонецПроцедуры &НаСервере Функция ИзменитьСтатусыНаСервере() // Итоговая статистика обработки. Результат = Новый Структура; Результат.Вставить("СменныхЗаданийНайдено", 0); Результат.Вставить("СменныхЗаданийСформировано", 0); Результат.Вставить("СменныхЗаданийФормируется", 0); Результат.Вставить("СменныхЗаданийПомечено", 0); Результат.Вставить("Найдено", 0); Результат.Вставить("Завершенных", 0); Результат.Вставить("Изменено", 0); Результат.Вставить("ЭтаповСОчищеннымРасходом", 0); Результат.Вставить("СтрокРасходаУдалено", 0); Результат.Вставить("ОперацийНайдено", 0); Результат.Вставить("ОперацийПомечено", 0); Результат.Вставить("Ошибок", 0); // Получаем таблицы формы как обычные ТаблицыЗначений. // При каждом новом запуске предыдущий протокол очищается. ТаблицаЭтапов = РеквизитФормыВЗначение("ЭтапыПроизводства"); ТаблицаОпераций = РеквизитФормыВЗначение("ПроизводственныеОперации"); ТаблицаЭтапов.Очистить(); ТаблицаОпераций.Очистить(); // Пользователь задает даты без времени. // Для поиска используем полностью первый и последний день периода. ДатаНачала = НачалоДня(НачалоПериода); ДатаОкончания = КонецДня(КонецПериода); // Здесь сохраняются ссылки только на те сменные задания, // которые эта обработка сама успешно перевела // из статуса "Закрыто" в статус "Сформировано". // // После пометки производственных операций на удаление // именно эти задания будут переведены в "Формируется". // // Сменные задания, которые до запуска обработки уже находились // в статусе "Сформировано", "Формируется" или другом статусе, // обработка автоматически возвращать в "Формируется" не будет. ПодготовленныеСменныеЗадания = Новый Массив; // ШАГ 1. ПОДГОТОВКА СМЕННЫХ ЗАДАНИЙ. // // ERP не позволяет изменять производственную операцию, // принадлежащую закрытому сменному заданию. // // Поэтому перед обработкой этапов и операций сменные задания // со статусом "Закрыто" штатно переводятся в "Сформировано". // // Статус документа непосредственно не присваивается. // Используется экспортная процедура менеджера документа: // // Документы.СменноеЗадание.УстановитьСтатус() // // Это штатный механизм ERP. Внутри него ERP выполняет блокировку // сменного задания, начинает транзакцию, изменяет статус документа // и выполняет предусмотренные конфигурацией действия с регистром // "ОперацииКСозданиюСменныхЗаданий" и производственными операциями. ВыборкаСменныхЗаданий = Документы.СменноеЗадание.Выбрать( ДатаНачала, ДатаОкончания); Пока ВыборкаСменныхЗаданий.Следующий() Цикл Результат.СменныхЗаданийНайдено = Результат.СменныхЗаданийНайдено + 1; Попытка ОбъектСменногоЗадания = ВыборкаСменныхЗаданий.Ссылка.ПолучитьОбъект(); Если ОбъектСменногоЗадания = Неопределено Тогда Продолжить; КонецЕсли; // Для снятия блокировки производственных операций // требуется изменить только закрытые сменные задания. Если ОбъектСменногоЗадания.Статус <> Перечисления.СтатусыСменныхЗаданий.Закрыто Тогда Продолжить; КонецЕсли; // Выполняем штатный переход: // // Закрыто -> Сформировано // // Проведенный вручную эксперимент показал, // что после этого производственные операции остаются // связанными со сменным заданием, но блокировка, // вызванная статусом "Закрыто", снимается. Документы.СменноеЗадание.УстановитьСтатус( ВыборкаСменныхЗаданий.Ссылка, Перечисления.СтатусыСменныхЗаданий.Сформировано); // Запоминаем только успешно подготовленное сменное задание. // После обработки производственных операций именно его // нужно будет перевести из "Сформировано" в "Формируется". ПодготовленныеСменныеЗадания.Добавить( ВыборкаСменныхЗаданий.Ссылка); Результат.СменныхЗаданийСформировано = Результат.СменныхЗаданийСформировано + 1; Исключение Результат.Ошибок = Результат.Ошибок + 1; Сообщить( "Не удалось перевести сменное задание " + Строка(ВыборкаСменныхЗаданий.Ссылка) + " из ""Закрыто"" в ""Сформировано"": " + ОписаниеОшибки()); КонецПопытки; КонецЦикла; // ШАГ 2. ОЧИСТКА РАСХОДА И ПОДГОТОВКА ЭТАПОВ ПРОИЗВОДСТВА. // // Производственные операции завершенного этапа ERP // не позволяет изменять. // // Поэтому завершенные этапы штатным механизмом ERP // переводятся в статус "Начат" и перепроводятся. // // В испытанной базе после проведения этап получал состояние // "Начат, Ожидает завершения", после чего связанные // производственные операции становились доступны // для установки пометки удаления. ВыборкаЭтапов = Документы.ЭтапПроизводства2_2.Выбрать( ДатаНачала, ДатаОкончания); Пока ВыборкаЭтапов.Следующий() Цикл // Считаем все найденные за период этапы. Результат.Найдено = Результат.Найдено + 1; // Строка таблицы создается только для завершенного этапа. СтрокаЭтапа = Неопределено; Попытка // Получаем объект этапа производства. ОбъектЭтапа = ВыборкаЭтапов.Ссылка.ПолучитьОбъект(); Если ОбъектЭтапа = Неопределено Тогда Продолжить; КонецЕсли; // Обрабатываем только завершенные этапы. Если ОбъектЭтапа.Статус <> Перечисления.СтатусыЭтаповПроизводства2_2.Завершен Тогда Продолжить; КонецЕсли; Результат.Завершенных = Результат.Завершенных + 1; // Перед изменением статуса полностью очищаем фактический // расход материалов и работ этапа. // // В ручном эксперименте именно удаление строк расхода // позволило затем отменить проведение документов передачи // материалов и многопроходно разобрать ремонтную цепочку. // // На первом варианте алгоритма не различаем обычные материалы // и промежуточные узлы: поскольку весь производственный контур // готовится к удалению, очищаем табличную часть целиком. КоличествоСтрокРасхода = ОбъектЭтапа.РасходМатериаловИРабот.Количество(); Если КоличествоСтрокРасхода > 0 Тогда ОбъектЭтапа.РасходМатериаловИРабот.Очистить(); Результат.ЭтаповСОчищеннымРасходом = Результат.ЭтаповСОчищеннымРасходом + 1; Результат.СтрокРасходаУдалено = Результат.СтрокРасходаУдалено + КоличествоСтрокРасхода; КонецЕсли; // Добавляем найденный завершенный этап // в таблицу результатов. // // В колонку "Этап" записывается настоящая ссылка // на документ, поэтому из формы можно работать // именно с объектом ERP, а не только с его // текстовым представлением. СтрокаЭтапа = ТаблицаЭтапов.Добавить(); СтрокаЭтапа.Этап = ВыборкаЭтапов.Ссылка; СтрокаЭтапа.Дата = ВыборкаЭтапов.Дата; СтрокаЭтапа.Номер = Строка(ВыборкаЭтапов.Номер); СтрокаЭтапа.ИсходныйСтатус = Строка(ОбъектЭтапа.Статус); СтрокаЭтапа.Результат = ""; СтрокаЭтапа.Ошибка = ""; // Запоминаем первоначальный статус. // Он требуется штатному механизму ERP, // обрабатывающему изменение статуса этапа. СтатусДоИзменения = ОбъектЭтапа.Статус; // Получаем штатные данные заполнения, // необходимые ERP при изменении статуса этапа. ДанныеЗаполнения = УправлениеПроизводством.ДанныеЗаполненияПриИзмененииСтатуса( ОбъектЭтапа); // Меняем статус: // // Завершен -> Начат ОбъектЭтапа.Статус = Перечисления.СтатусыЭтаповПроизводства2_2.Начат; // Одного присваивания нового статуса недостаточно. // // Вызываем штатный механизм ERP, который приводит // связанные реквизиты этапа в состояние, // соответствующее новому статусу. УправлениеПроизводством.ЗаполнитьРеквизитыЭтапаПриИзмененииСтатуса( ОбъектЭтапа, СтатусДоИзменения, ДанныеЗаполнения); // Ключевой момент. // // Этап необходимо не просто записать, а провести. // // В испытанной базе после проведения ERP переводила // этап в состояние: // // "Начат, Ожидает завершения" // // После этого связанные производственные операции // становились доступны для установки пометки удаления. ОбъектЭтапа.Записать( РежимЗаписиДокумента.Проведение); Результат.Изменено = Результат.Изменено + 1; // Фиксируем успешный результат в таблице. СтрокаЭтапа.Результат = "Переведен в Начат"; СтрокаЭтапа.Ошибка = ""; Исключение Результат.Ошибок = Результат.Ошибок + 1; // Если строка таблицы уже была создана, // сохраняем в ней диагностическую информацию. Если СтрокаЭтапа <> Неопределено Тогда СтрокаЭтапа.Результат = "Не изменен"; СтрокаЭтапа.Ошибка = ОписаниеОшибки(); КонецЕсли; // Дополнительно выводим ошибку // в стандартные сообщения 1С. Сообщить( "Не удалось изменить этап " + Строка(ВыборкаЭтапов.Ссылка) + ": " + ОписаниеОшибки()); КонецПопытки; КонецЦикла; // ШАГ 3. ПОМЕТКА ПРОИЗВОДСТВЕННЫХ ОПЕРАЦИЙ НА УДАЛЕНИЕ. // // К этому моменту должны быть сняты две возможные // статусные блокировки производственной операции: // // 1. закрытое сменное задание переведено в "Сформировано"; // 2. завершенный этап производства переведен в "Начат". // // После этого производственные операции можно штатно // пометить на удаление. // // Физическое удаление документов здесь не выполняется. // Продолжают действовать все штатные проверки ERP. ВыборкаОпераций = Документы.ПроизводственнаяОперация2_2.Выбрать( ДатаНачала, ДатаОкончания); Пока ВыборкаОпераций.Следующий() Цикл Результат.ОперацийНайдено = Результат.ОперацийНайдено + 1; СтрокаОперации = Неопределено; Попытка // Получаем объект производственной операции. ОбъектОперации = ВыборкаОпераций.Ссылка.ПолучитьОбъект(); Если ОбъектОперации = Неопределено Тогда Продолжить; КонецЕсли; // Добавляем операцию в таблицу результатов. СтрокаОперации = ТаблицаОпераций.Добавить(); СтрокаОперации.Операция = ВыборкаОпераций.Ссылка; СтрокаОперации.Этап = ОбъектОперации.Этап; СтрокаОперации.Номер = Строка(ВыборкаОпераций.Номер); СтрокаОперации.Статус = Строка(ОбъектОперации.Статус); СтрокаОперации.Помечена = ОбъектОперации.ПометкаУдаления; СтрокаОперации.Результат = ""; СтрокаОперации.Ошибка = ""; // Если операция уже была помечена на удаление, // повторно ее не изменяем. // // В таблице при этом показываем ее фактическое состояние. Если ОбъектОперации.ПометкаУдаления Тогда СтрокаОперации.Помечена = Истина; СтрокаОперации.Результат = "Уже помечена на удаление"; Продолжить; КонецЕсли; // Устанавливаем стандартную пометку удаления. ОбъектОперации.УстановитьПометкуУдаления(Истина); Результат.ОперацийПомечено = Результат.ОперацийПомечено + 1; // Отражаем успешный результат в таблице. СтрокаОперации.Помечена = Истина; СтрокаОперации.Результат = "Помечена на удаление"; СтрокаОперации.Ошибка = ""; Исключение Результат.Ошибок = Результат.Ошибок + 1; // Если строка уже была создана, // сохраняем в ней диагностическую информацию. Если СтрокаОперации <> Неопределено Тогда СтрокаОперации.Помечена = Ложь; СтрокаОперации.Результат = "Не помечена"; СтрокаОперации.Ошибка = ОписаниеОшибки(); КонецЕсли; Сообщить( "Не удалось пометить операцию " + Строка(ВыборкаОпераций.Ссылка) + ": " + ОписаниеОшибки()); КонецПопытки; КонецЦикла; // ШАГ 4. ПОВТОРНЫЙ ПОИСК СМЕННЫХ ЗАДАНИЙ, // ВОЗВРАТ В "ФОРМИРУЕТСЯ" И УСТАНОВКА ПОМЕТКИ УДАЛЕНИЯ. // // ВАЖНО: // здесь нельзя использовать только массив // ПодготовленныеСменныеЗадания. // // Этот массив содержит лишь те задания, которые именно текущий // запуск обработки перевел из "Закрыто" в "Сформировано". // Если перед производственной обработкой уже запускалась V3, // часть сменных заданий может к этому моменту уже находиться // в состоянии "Сформировано". Такие задания также необходимо // подготовить к удалению. // // Поэтому на этом шаге сменные задания за выбранный период // запрашиваются заново. В работу берутся ВСЕ задания, // которые фактически находятся в состоянии "Сформировано", // независимо от того, каким предыдущим действием они были // приведены в это состояние. // // После пометки производственных операций на удаление // выполняется штатный переход: // // Сформировано -> Формируется // // После успешного перехода сменному заданию устанавливается // стандартная пометка удаления. // // Используется несколько проходов. Если в текущем проходе // удалось подготовить хотя бы одно задание, оставшиеся задания // проверяются повторно. ЗапросСменныхЗаданийФормируется = Новый Запрос; ЗапросСменныхЗаданийФормируется.Текст = "ВЫБРАТЬ | СменноеЗадание.Ссылка КАК Ссылка |ИЗ | Документ.СменноеЗадание КАК СменноеЗадание |ГДЕ | СменноеЗадание.Дата МЕЖДУ &НачалоПериода И &КонецПериода | И СменноеЗадание.Статус = | ЗНАЧЕНИЕ(Перечисление.СтатусыСменныхЗаданий.Сформировано) | И НЕ СменноеЗадание.ПометкаУдаления"; ЗапросСменныхЗаданийФормируется.УстановитьПараметр( "НачалоПериода", НачалоПериода); ЗапросСменныхЗаданийФормируется.УстановитьПараметр( "КонецПериода", КонецПериода); ВыборкаСменныхЗаданийФормируется = ЗапросСменныхЗаданийФормируется.Выполнить().Выбрать(); ОставшиесяСменныеЗадания = Новый Массив; Пока ВыборкаСменныхЗаданийФормируется.Следующий() Цикл ОставшиесяСменныеЗадания.Добавить( ВыборкаСменныхЗаданийФормируется.Ссылка); КонецЦикла; Пока ОставшиесяСменныеЗадания.Количество() > 0 Цикл УспешноЗаПроход = 0; СледующийПроход = Новый Массив; Для Каждого СсылкаСменногоЗадания Из ОставшиесяСменныеЗадания Цикл Попытка ОбъектСменногоЗадания = СсылкаСменногоЗадания.ПолучитьОбъект(); Если ОбъектСменногоЗадания = Неопределено Тогда Продолжить; КонецЕсли; // Состояние проверяется повторно непосредственно // перед изменением документа. Если ОбъектСменногоЗадания.Статус = Перечисления.СтатусыСменныхЗаданий.Сформировано Тогда Документы.СменноеЗадание.УстановитьСтатус( СсылкаСменногоЗадания, Перечисления.СтатусыСменныхЗаданий.Формируется); Результат.СменныхЗаданийФормируется = Результат.СменныхЗаданийФормируется + 1; ИначеЕсли ОбъектСменногоЗадания.Статус <> Перечисления.СтатусыСменныхЗаданий.Формируется Тогда Продолжить; КонецЕсли; // После штатного изменения статуса объект получаем заново. ОбъектСменногоЗадания = СсылкаСменногоЗадания.ПолучитьОбъект(); Если ОбъектСменногоЗадания <> Неопределено И НЕ ОбъектСменногоЗадания.ПометкаУдаления Тогда ОбъектСменногоЗадания.УстановитьПометкуУдаления( Истина); Результат.СменныхЗаданийПомечено = Результат.СменныхЗаданийПомечено + 1; КонецЕсли; УспешноЗаПроход = УспешноЗаПроход + 1; Исключение // Ошибка промежуточного прохода пока не считается // окончательной. После обработки других заданий // повторим попытку. СледующийПроход.Добавить( СсылкаСменногоЗадания); КонецПопытки; КонецЦикла; Если СледующийПроход.Количество() = 0 Тогда Прервать; КонецЕсли; Если УспешноЗаПроход = 0 Тогда // Целый проход не дал результата. // Теперь ошибки считаются окончательными. Для Каждого СсылкаСменногоЗадания Из СледующийПроход Цикл Попытка ОбъектСменногоЗадания = СсылкаСменногоЗадания.ПолучитьОбъект(); Если ОбъектСменногоЗадания = Неопределено Тогда Продолжить; КонецЕсли; Если ОбъектСменногоЗадания.Статус = Перечисления.СтатусыСменныхЗаданий.Сформировано Тогда Документы.СменноеЗадание.УстановитьСтатус( СсылкаСменногоЗадания, Перечисления.СтатусыСменныхЗаданий.Формируется); КонецЕсли; ОбъектСменногоЗадания = СсылкаСменногоЗадания.ПолучитьОбъект(); Если ОбъектСменногоЗадания <> Неопределено И НЕ ОбъектСменногоЗадания.ПометкаУдаления Тогда ОбъектСменногоЗадания.УстановитьПометкуУдаления( Истина); КонецЕсли; Исключение Результат.Ошибок = Результат.Ошибок + 1; Сообщить( "Не удалось подготовить сменное задание " + Строка(СсылкаСменногоЗадания) + " к удалению: " + ОписаниеОшибки()); КонецПопытки; КонецЦикла; Прервать; КонецЕсли; ОставшиесяСменныеЗадания = СледующийПроход; КонецЦикла; // После заполнения обычных ТаблицЗначений // записываем их обратно в реквизиты формы. ЗначениеВРеквизитФормы( ТаблицаЭтапов, "ЭтапыПроизводства"); ЗначениеВРеквизитФормы( ТаблицаОпераций, "ПроизводственныеОперации"); // Возвращаем клиентской процедуре итоговую статистику. Возврат Результат; КонецФункции
Алгоритм удаления документов
В результате получилась последовательность массового удаления документов производства, в которой «Универсальная обработка» запускается дважды.
Первый запуск «Универсальной обработки». Обработка многопроходно отменяет проведение документов и устанавливает пометки удаления там, где это уже возможно. Тем самым удаляется часть зависимостей, мешающих дальнейшей обработке производственного контура.
«Производственная обработка». Обработка подготавливает специфические объекты производственного контура: сменные задания, этапы производства и производственные операции. Она изменяет состояния сменных заданий и этапов производства, очищает расход материалов и работ и устанавливает пометки удаления производственным операциям и подготовленным сменным заданиям.
Второй запуск «Универсальной обработки». После изменений, выполненных «Производственной обработкой», «Универсальная обработка» повторно проходит по документам, отменяет проведение оставшихся документов и устанавливает им пометки удаления.
Штатные механизмы 1С:ERP. Очищаются ранее сформированные расчетные движения, после чего стандартная обработка «Удаление помеченных объектов» выполняет физическое удаление.
Решение тестировалось на версии платформы 1С:Предприятие 8.3.27.2130 для разработчиков, конфигурация 1С:ERP Управление предприятием 2 (2.5.25.80).
В качестве базы примера использовалась учебная база, содержащая разнообразные производственные документы, включая производственные операции, сменные задания, документы ремонта собственного оборудования и многоэтапного ремонта давальческого оборудования.
После первого запуска «Универсальной обработки», пытающейся отменить проведение и установить пометки удаления всем найденным документам выбранного периода, результат выглядел следующим образом:

Далее была запущена «Производственная обработка», которая подготовила специфические объекты производственного контура: изменила состояния сменных заданий и этапов производства, очистила расход материалов и работ и установила пометки удаления производственным операциям и подготовленным сменным заданиям.

Затем «Универсальная обработка» была запущена повторно. В результате ее работы все документы, созданные в выбранном периоде, были помечены на удаление.

Затем открываем Регламентные операции по закрытию месяца в подсистеме Финансовый результат и контроллинг и переходим в Настройки → Настройка параметров операций закрытия месяца, где включаем техническую настройку Режим отладки расчета = Да.


Жмем кнопку Сохранить и закрыть.
После этого для операции Распределение затрат и расчет себестоимости становятся доступны дополнительные параметры отладки. Для нашей задачи нужны два из них:
Перед расчетом очищать старые расчетные движения = Да;
Не выполнять расчет себестоимости = Да.
Первый параметр заставляет систему перед выполнением операции очистить ранее сформированные расчетные движения. Второй позволяет на этом остановиться: заново рассчитывать себестоимость документов, которые мы собираемся удалить, очевидно, не требуется.
Чтобы установить эти настройки, опять заходим из Регламентные операции по закрытию месяца в Настройки — Параметры операций закрытия месяца, в Операции вставляем Распределение затрат и расчет себестоимости.

Устанавливаем в нужных местах Да и жмем кнопку Сохранить и закрыть.
После установки параметров в операциях закрытия месяца достаточно выполнить только операцию Распределение затрат и расчет себестоимости. Выполнять заново все операции закрытия месяца не обязательно.
Таким образом, мы не удаляем записи расчетных регистров непосредственно и не пытаемся обходить механизмы 1С:ERP. Наоборот, используем штатную операцию закрытия месяца для очистки созданных ею же расчетных данных.
После очистки расчетных движений запускаем штатную встроенную обработку 1С:ERP Удаление помеченных объектов.
После ее работы все документы выбранного периода были физически удалены. В базе остались только помеченные на удаление документы, относящиеся к другим периодам.
Резюме
Таким образом, последовательность «Универсальная обработка» → «Производственная обработка» → повторный запуск «Универсальной обработки» → штатные механизмы 1С:ERP позволила полностью удалить документы выбранного периода, включая связанные с производством объекты, которые первоначально блокировали работу универсального алгоритма.
Первый запуск «Универсальной обработки» удаляет доступные ему зависимости между документами и помечает на удаление документы, которые может. Затем «Производственная обработка» подготавливает специфические объекты производственного контура: сменные задания, этапы производства и производственные операции. После этого повторный запуск «Универсальной обработки» отменяет проведение оставшихся документов и устанавливает им пометки удаления.
При этом эти внешние обработки не удаляют записи регистров напрямую и не отключают контрольные механизмы конфигурации. Расчетные движения очищаются штатным механизмом закрытия месяца, а окончательное физическое удаление выполняется стандартной обработкой 1С:ERP «Удаление помеченных объектов».