Массовое удаление документов производства в 1С:ERP

В предыдущей статье было описано, как массово находить документы за выбранный период, отменять их проведение и помечать на удаление. Это распространенная задача, а штатных средств для ее решения в программе нет. Мной была создана внешняя обработка, которая в несколько проходов последовательно удаляет доступные ей зависимости между документами, отменяет их проведение и устанавливает пометки удаления.
Однако при испытании обработки на базе с документами производства выяснилось, что существует отдельная группа объектов, с которой такой универсальный алгоритм не справляется. Проблемы возникли с завершенными этапами, производственными операциями, сменными заданиями, а при ремонтах — с отраженными в этапах расходах материалов и работ.
Документы оказались накрепко связаны между собой в замкнутые цепочки: один документ не желает меняться, пока не изменится второй, а второй — пока не изменится первый. Для разрыва таких цепочек понадобилась еще одна — «Производственная обработка».
Алгоритм «Производственной обработки»
Код обработки решает четыре задачи:
1. Подготовка сменных заданий. Обработка находит сменные задания за выбранный период, находящиеся в закрытом состоянии. Такие задания сначала переводятся из состояния Закрыто в состояние Сформировано. Это необходимо, чтобы снять ограничения, связанные с завершенными сменными заданиями, и подготовить связанные производственные объекты к дальнейшей обработке.
2. Подготовка этапов производства и устранение связанных с ними материальных зависимостей. У каждого найденного этапа очищается табличная часть РасходМатериаловИРабот, после чего этап штатными средствами конфигурации переводится из состояния Завершен в состояние Начат. Простого изменения реквизита Статус недостаточно: обработка вызывает стандартную логику 1С:ERP изменения статуса и затем записывает документ с проведением. В результате этап отображается в системе как Начат, Ожидает завершения.
3. Установка пометки удаления производственным операциям. После подготовки этапов обработка находит относящиеся к производству операции и пытается установить для них стандартную пометку удаления. Непосредственного удаления объектов из информационной базы не производится. Если штатные проверки 1С:ERP не позволяют пометить конкретную операцию на удаление, объект остается без изменения, а ошибка фиксируется для диагностики.
4. Подготовка сменных заданий к удалению. После обработки этапов и производственных операций обработка повторно ищет за выбранный период все сменные задания, находящиеся в состоянии Сформировано. При этом не имеет значения, были они переведены в это состояние текущим запуском обработки или находились в нем ранее. Найденные задания штатными средствами 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. Первый запуск «Универсальной обработки». Обработка многопроходно отменяет проведение документов и устанавливает пометки удаления там, где это уже возможно. Тем самым удаляется часть зависимостей, мешающих дальнейшей обработке производственного контура.
2. «Производственная обработка». Обработка подготавливает специфические объекты производственного контура: сменные задания, этапы производства и производственные операции. Она изменяет состояния сменных заданий и этапов производства, очищает расход материалов и работ и устанавливает пометки удаления производственным операциям и подготовленным сменным заданиям.
3. Второй запуск «Универсальной обработки». После изменений, выполненных «Производственной обработкой», «Универсальная обработка» повторно проходит по документам, отменяет проведение оставшихся документов и устанавливает им пометки удаления.
4. Штатные механизмы 1С:ERP. Очищаются ранее сформированные расчетные движения, после чего стандартная обработка «Удаление помеченных объектов» выполняет физическое удаление.
Решение тестировалось на версии платформы 1С:Предприятие 8.3.27.2130 для разработчиков, конфигурация 1С:ERP Управление предприятием 2 (2.5.25.80).
В качестве базы примера использовалась учебная база, содержащая разнообразные производственные документы, включая производственные операции, сменные задания, документы ремонта собственного оборудования и многоэтапного ремонта давальческого оборудования.
После первого запуска «Универсальной обработки», пытающейся отменить проведение и установить пометки удаления всем найденным документам выбранного периода, результат выглядел следующим образом:

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

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

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


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

Устанавливаем в нужных местах Да и жмем кнопку Сохранить и закрыть.
После установки параметров в операциях закрытия месяца достаточно выполнить только операцию Распределение затрат и расчет себестоимости. Выполнять заново все операции закрытия месяца не обязательно.
Таким образом, мы не удаляем записи расчетных регистров непосредственно и не пытаемся обходить механизмы 1С:ERP. Наоборот, используем штатную операцию закрытия месяца для очистки созданных ею же расчетных данных.
После очистки расчетных движений запускаем штатную встроенную обработку 1С:ERP Удаление помеченных объектов.
После ее работы все документы выбранного периода были физически удалены. В базе остались только помеченные на удаление документы, относящиеся к другим периодам.
Резюме
Таким образом, последовательность «Универсальная обработка» → «Производственная обработка» → повторный запуск «Универсальной обработки» → штатные механизмы 1С:ERP позволила полностью удалить документы выбранного периода, включая связанные с производством объекты, которые первоначально блокировали работу универсального алгоритма.
Первый запуск «Универсальной обработки» удаляет доступные ему зависимости между документами и помечает на удаление документы, которые может. Затем «Производственная обработка» подготавливает специфические объекты производственного контура: сменные задания, этапы производства и производственные операции. После этого повторный запуск «Универсальной обработки» отменяет проведение оставшихся документов и устанавливает им пометки удаления.
При этом эти внешние обработки не удаляют записи регистров напрямую и не отключают контрольные механизмы конфигурации. Расчетные движения очищаются штатным механизмом закрытия месяца, а окончательное физическое удаление выполняется стандартной обработкой 1С:ERP "Удаление помеченных объектов".
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.