The Jerusalem PostStudent opens fire outside school in Turkey, eight pupils wounded, NTV reportsDaily MaverickStudent opens fire outside school in Turkey, eight pupils wounded, NTV reportsוואלהבמהלך חג הסוכות תוגבל כניסה למטיילים במשטחי אימונים בדרוםBollywood HungamaEXCLUSIVE: Ajay Devgn-Rohit Jugraj’s horror thriller titled SuryasparshInquirer EntertainmentJopay Paguia ‘respects’ Rochelle Pangilinan, but stands firm on her work ethicInquirerAgusan solon pushes national soil strategy through SUCsХабрКак в игровых студиях принимаются технические решения, когда на кону денюжкиCollider‘Marvel’s Wolverine’ Officially Changes Controversial Gameplay Feature After Fan BacklashSouth China Morning PostCan China’s grain reserves protect food security against El Nino?The South AfricanAircraft crash reported near Morningstar Airfield on the N7RTL BoulevardRekenkamer: Van Weel zette Kamer op verkeerde been over 10.000 onbehandelde aangiftenGhaflaBoundaries And Public Office: Omanga’s School Attire Trend Sparks Debate Online
The Daily Newsstand · Free, Always
Tuesday, September 22, 2026

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

Translate

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

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

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

Алгоритм «Производственной обработки»

Код обработки решает четыре задачи:

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 "Удаление помеченных объектов".

View the original on Хабр

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.