Жизнь после проведения. Мастерим костыли

20.10.22

Разработка - Механизмы типовых конфигураций

Пробуем отловить момент после окончания проведения документа.

Вступительное слово

Типовые средства платформы не предоставляют события "После проведения", хотя данная тема весьма популярна в поисковиках.

Что же можно использовать из типовых возможностей? Событие "ПослеЗаписиНаСервере" формы объекта документа: "жирный" минус - актуально только для интерактивного проведения из формы объекта. Отчасти можно использовать в каких-то локальных случаях. Но для широкого применения, прежде всего при программном создании документов, данное событие не подходит.

А есть ли что-то в типовых конфигурациях? Если взять семейство конфигурация УТК/КА/ERP, то там можно найти функционал автоматического формирования расходных ордеров на товары. Вкратце алгоритм приблизительно следующий:

  1. Формируется таблица изменений движений документа по регистру накопления ТоварыКОтгрузке
  2. В событии ПриЗаписи модуля набора записей регистра накопления ТоварыКОтгрузке вызывается процедура переоформления ордеров:
    1. Выполняется запись в специальный регистр сведений ОчередьПереоформленияРасходныхОрдеров
    2. В фоновом режиме (в файловом варианте работы не в фоне) запускается процедура переоформления ордеров
    3. После успешного переоформления ордеров регистр сведений ОчередьПереоформленияРасходныхОрдеров очищается

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

 

Практическое применение

Так для чего же нужно отлавливать событие ПослеПроведения? Пример - под спойлером!

 
 Немного предистории: прикладной пример использования

 

Первое приближение

Первое, что пришло в голову - пробуем установить на документ исключительную блокировку: получилось - транзакция проведения завершена. Частично это проблему решило:

  • блокировку установили --> исходный документ проведен --> выполняем нужные действия
  • блокировку установить не удалось --> записываем ссылку на исходный документ в регистр очереди --> регламентным заданием выполняем нужные действия

Но при таком алгоритме действий в час-пик мы получаем вываливание всех документов в очередь с последующей обработкой регламентным заданием. Менеджеры сразу впали в глубокую тоску.

 

Итоговый костыль

Идею попытки установки исключительной блокировки требовалось развить, так как пока это единственный универсальный "железный" метод проверки окончания проведения документа (коллеги, буду рад другим вариантам!). Логично, что необходимо в случае неудачной блокировки сделать паузу и попытаться заблокировать еще раз. Опять приплыли: нативной паузы в платформе нет. На счастье параллельно велась разработка обмена с http-сервисом и на ум пришло http-соединение с указанием таймаута. Как оказалось в последствие, идея оказалась не нова) Итого сложилась следующая картина:

  1. Назначаем количество попыток блокировки документа, чтобы в случае чего не уйти в бесконечный цикл
  2. Определяемся с паузой между попытками блокировки
  3. В качестве паузы используем http-запрос на недоступный ip-адрес

Итоговая функция для проверки окончания проведения документа

 
 Листинг функции
Функция ДождатьсяЗавершенияПроведения(ИсходныйДокумент, Попыток = 5, Таймаут = 5) Экспорт
	
	
	СоединениеФиктивное = Новый HTTPСоединение("1.2.3.4",,,,,Таймаут);
	ЗапросФиктивный 	= Новый HTTPЗапрос("/example");
	

    Для К = 1 По Попыток Цикл
		
		
		Попытка
			
			НачатьТранзакцию(РежимУправленияБлокировкойДанных.Управляемый);
			Блокировка 				= Новый БлокировкаДанных;
			ЭлементБлокировки 		= Блокировка.Добавить("Документ."+ИсходныйДокумент.Метаданные().Имя);
			ЭлементБлокировки.УстановитьЗначение("Ссылка", ИсходныйДокумент);
			ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;

			Блокировка.Заблокировать();
			ЗафиксироватьТранзакцию();
			
			// если удалось заблокировать, то проведение закончено
			Возврат Истина;
			
		Исключение
			
			ОтменитьТранзакцию();
			
		КонецПопытки;
		
		Попытка
			
			// Перед следующей попыткой блокировки документа
			// делаем паузу длительностью в Таймаут секунд
			ОтветПауза = СоединениеФиктивное.Получить(ЗапросФиктивный);
			
			
		Исключение
			
		КонецПопытки;
		
	КонецЦикла;
	
	
	
	Возврат Ложь;

КонецФункции

 

 

Естественно, большое ограничение на использование - вызываться она должна вне транзакции записи документа. Плюс не дает 100% гарантии, если мы ограничиваем количество попыток установки блокировки. Для приведенного ранее практического применения это вполне подходило, так как все действия, которые необходимо было выполнять после проведения, производились в отдельном сеансе фонового задания.

Данное решение не претендует на "истину в первой инстанции", так что с удовольствием почитаю как критику (не спорю, возможно что-то мог важное упустить), так и альтернативные варианты решения данной задачи!

См. также

СКД Механизмы типовых конфигураций Запросы Программист Платформа 1С v8.3 1С:Зарплата и кадры государственного учреждения 3 1С:Зарплата и Управление Персоналом 3.x Россия Бесплатно (free)

Работая с типовыми отчетами в конфигурациях «Зарплата и управление персоналом, редакция 3», «Зарплата и кадры государственного учреждения, редакция 3» и подобных, в схемах компоновки данных можно встретить конструкции запросов, которые обращаются к некоторым виртуальным таблицам.

20.08.2024    1737    PROSTO-1C    0    

18

Механизмы типовых конфигураций Программист Платформа 1С v8.3 1С:Комплексная автоматизация 2.х Россия Бесплатно (free)

Эта ошибка была обнаружена мной в типовой конфигурации 1С:Комплексная автоматизация 2 (2.5.16.115), БСП версия 3.1.9.302. Возникает она после того, как вы добавляете в расширение бизнес-процесс или задачу, выполняете обновление идентификаторов метаданных расширений, но ошибка при записи любого элемента справочника "Профили групп доступа" всё равно остаётся.

01.07.2024    1747    Vidz    0    

11

Механизмы типовых конфигураций Программист Платформа 1С v8.3 Конфигурации 1cv8 Россия Бесплатно (free)

Очень часто в написании кода требуется обращаться к предопределённым значениям. Если идёт обращение к типовым предопределённым значениям, то проблем не возникает.

24.06.2024    1106    olja-ljaaa    0    

3

Механизмы типовых конфигураций Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Статистическая выборка сценариев и точек изменения отчетов на общей форме ФормаОтчета в типовых конфигурациях. Примеры кода.

03.06.2024    4891    Serg2000mr    32    

108

Механизмы типовых конфигураций Ценообразование, анализ цен Программист Пользователь Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 Россия Абонемент ($m)

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

1 стартмани

11.04.2024    1058    tango    5    

3
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. user1466751 18 15.09.22 10:56 Сейчас в теме
1. В ПриЗаписи документа накладываете исключительную блокировку на него.
2. Запускаете фоновое задание с нужным кодом.
3. В фоном задании в самом начале накладываете неисключительную блокировку на документ.
4. Фоновое ждет окончания транзакции записи документа из п.1 и только после ее окончания продолжает выполнение кода.
5. Профит.

Исключение: массовая запись документов в п.1 в одной транзакции (КД какая-нибудь). Решение: не делать в одной транзакции массовой записи :)
2. RocKeR_13 1366 15.09.22 11:10 Сейчас в теме
(1)
1. В ПриЗаписи документа накладываете исключительную блокировку на него.

Зачем еще раз на проводимый документ устанавливать исключительную блокировку?

Данный алгоритм использовал: довольно часто на п.3 блокировка выпадала в исключение из-за превышения времени ожидания блокировки.
3. user1466751 18 15.09.22 11:12 Сейчас в теме
(2)
Чтобы фоновое задание дождалось окончания транзакции записи документа.

Чтобы не было превышения времени блокировки не изменяйте в длинной транзакции много документов.
4. RocKeR_13 1366 15.09.22 11:16 Сейчас в теме
(3) При проведении и так накладывается блокировка на документ.

Чтобы не было превышения времени блокировки не изменяйте в длинной транзакции много документов.

Это от лукавого) Контролировать это почти невозможно
5. user1466751 18 15.09.22 11:29 Сейчас в теме
(4)
Значит, минус первый пункт.

Почему невозможно? Вы же управляете процессами в базе.
В целом первопричина у вас в локальных пиках, но решение с паузой не решает эту проблему. Если транзакции короткие, то и с регистром и ожиданием на блокировке все отработает. Если транзакция длинная, то точно так же после ее завершения у вас вываливается большое количество доков к обработке, что и из РС в пике.
В чем ценность такого решения перед регистром и регзаданием при сохранении длинных транзакций?
6. RocKeR_13 1366 15.09.22 11:38 Сейчас в теме
(5) Я там ничем не управляю: в базу вносят доработки несколько разных компаний + настройки автоматического формирования определяются в пользовательском режиме для произвольных документов + могут запускать закрытие месяца в рабочее время + есть интеграции с сайтом и кучей разных web/http-сервисов. Поэтому я и пишу: в большинстве случаев вами предложенный алгоритм, действительно, работает. Но в некоторых ситуациях и для некоторых видов документов периодически вываливается. Подобрав нужную паузу и нужное количество итераций предложенный способ значительно уменьшает количество таких ситуаций. Да, естественно, предложенный метод не полностью гарантирует нам, что мы дождемся окончания транзакции, если только не организуем бесконечный цикл ожидания. Сейчас, например, 5 итераций с паузой в 5 секунд пока полностью исключил выпадание документов в регистр заданий.
7. user1466751 18 15.09.22 11:43 Сейчас в теме
(6)
5*5 = 25. По умолчанию ожидание на блокировке 20 секунд. Может стоило до 30 поднять и не париться?)

PS Сочувствую с отсутствием управления.
8. RocKeR_13 1366 15.09.22 11:46 Сейчас в теме
(7) Поднимем при необходимости) В принципе большинство процессов на моей совести, но я отношусь только к одной из сопровождающих компаний. В целом-то всё не так уж и плохо)
9. coollerinc 196 09.11.22 11:55 Сейчас в теме
Пауза есть в БСП или в БТС. Делается с помощью ожидания фонового задания.

// Останавливает выполнение кода на заданное время.
//
// Параметры:
//  Секунд - Число - время ожидания в секундах.
//
Процедура Пауза(Секунд) Экспорт
	
	ТекущийСеансИнформационнойБазы = ПолучитьТекущийСеансИнформационнойБазы();
	ФоновоеЗадание = ТекущийСеансИнформационнойБазы.ПолучитьФоновоеЗадание();
	
	Если ФоновоеЗадание = Неопределено Тогда
		Параметры = Новый Массив;
		Параметры.Добавить(Секунд);
		ФоновоеЗадание = ФоновыеЗадания.Выполнить("ОбщегоНазначенияБТС.Пауза", Параметры);
	КонецЕсли;
		
	ФоновоеЗадание.ОжидатьЗавершенияВыполнения(Секунд);
	
КонецПроцедуры
Показать
Оставьте свое сообщение