Самодельный обработчик ПослеЗаписи объекта
Разработка - Механизмы платформы 1С
Бесплатные
ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.
Узнавайте о новых бесплатных решениях в нашей телеграм-группе Инфостарт БЕСПЛАТНО
| Наименование | Скачано | Бесплатно |
|---|---|---|
|
Демо база
.dt 110,23Kb
64
|
64 | Скачать бесплатно |
Вы можете заказать платную доработку или адаптацию этой разработки под вашу конфигурацию на «Бирже заказов».
- 0% комиссии — оплата напрямую исполнителю;
- Исполнители любого масштаба — от отдельных специалистов до команд под проект;
- Прямой обмен контактами между заказчиком и исполнителем;
- Безопасная сделка — при необходимости;
- Рейтинги, кейсы и прозрачная система откликов.
Статья актуальна для 8.3.22. Описанный в статье способ совместим с платформой 8.1 (немного отличается запись движений).
Статья НЕ рекомендуется к применению начинающими разработчиками, т.к. требует глубокого понимания рассмотренных механизмов платформы.
В управляемой форме объекта БД есть событие ПослеЗаписиНаСервере, но иногда хочется еще и обработчик ПослеЗаписи самого объекта. Он может быть полезен для выполнения необязательных действий, например оперативного запуска фонового задания обработки очереди, в которую записанный объект помещен и которая обрабатывается регламентным заданием.
Самым простым способом решения задачи является использование события ОбработкаПослеЗаписиВерсийИсторииДанных менеджера, которое выполняется в отдельном фоновом задании. Но он не дает доступа к не хранимому в БД состоянию объекта (свойства ОбменДанными и ДополнительныеСвойства) и требует включать историю данных для объекта. Поэтому рассмотрим более сложное решение.
Ранее в статье Безопасная работа с транзакциями во встроенном языке в разделе "Разрыв неявной транзакции" я описал как можно досрочно завершить транзакцию записи объекта, если она открыта неинтерактивно (не из формы объекта). Там я не рекомендовал применять этот прием в рабочем коде из-за ряда условий, которые нужно соблюдать для надежной работы такого кода. Теперь показываю как его применить для реализации обработчика ПослеЗаписи объекта. Наша цель - обеспечить выполнение кода
ЗафиксироватьТранзакцию(); // Фиксируем неявную транзакцию
// Делаем что то после транзакции записи
НачатьТранзакцию(); // Открывает фиктивную транзакцию, чтобы платформенная фиксация транзакции не вызвала ошибку
последним среди всех возможных обработчиков записи:
- обработчики событий записи
- обработчики подписок на события
- расширения обработчиков
- регистрация на узлах планов обмена (платформа)
- запись движений (платформа)
Тогда явное завершение транзакции не повлечет нарушения атомарности (неделимости) внесения изменений в БД.
Для достижений столь амбициозной цели нам понадобится механизм динамического подключения/отключения обработчиков объекта - операторы ДобавитьОбработчик и УдалитьОбработчик. Они легко находятся в синтакс-помощнике. Они по факту всегда добавляют обработчик в самый конец очереди обработчиков события конкретного объекта (проверено на 8.1, 8.2, 8.3.22), однако в документации это явно не обозначено. Вероятность изменения этого поведения в платформе представляется крайне низкой, т.к.
- платформа создает очереди обработчиков для всех событий объекта сразу при его создании
- если подключать обработчик не последним, то при подключении внутри обработки события будет риск что он не выполнится в текущем обходе очереди
У большинства типов метаданных последним в транзакции неинтерактивной записи выполняется событие ПриЗаписи. Поэтому нам нужно будет подключать обработчик на него. Но у документов это может быть и ОбработкаПроведения.
В транзакции интерактивной записи, т.е. открытой записью из формы объекта последним в транзакции всегда выполняется событие ПриЗаписиНаСервере. Подписаться на него невозможно. К тому же разорвать интерактивную транзакцию невозможно (вероятно ошибка платформы). Поэтому в транзакции интерактивной записи не будем разрывать транзакцию и будем вызывать обработчик ПослеЗаписи перед событием ПриЗаписиНаСервере. Такое решение кажется приемлемым, т.к. запись в форме выполняется реже, чем неинтерактивная запись объектов.
Создадим подписку на событие ПередЗаписью для документов и подписку на событие ПередЗаписью для остальных ссылочных типов объектов, у которых хотим создать обработчик ПослеЗаписи. Подключим внутри этих подписок динамический обработчик на последнее событие транзакции. А в самом динамическом обработчике последнего события выполним явно
- регистрацию на узлах планов обмена, т.к. платформа выполняет ее в самом конце неявной транзакции записи и потому теперь мы должны сделать это за нее
- запись наборов движений документа (начиная с 8.2 только с установленным свойством "Записывать"), т.к. платформа их записывает сразу после события ОбработкаПроведения
// Подписки ПередЗаписью
Процедура ОбъектПередЗаписью(Источник, Отказ) Экспорт
Сообщить("Подписка1 ПередЗаписью. Динамическое подключение обработчика");
УдалитьОбработчик Источник.ПриЗаписи, ПриЗаписиПоследний;
Добавитьобработчик Источник.ПриЗаписи, ПриЗаписиПоследний;
КонецПроцедуры
Процедура ДокументПередЗаписью(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
Сообщить("Подписка1 ПередЗаписью. Динамическое подключение обработчика");
УдалитьОбработчик Источник.ПриЗаписи, ПриЗаписиПоследний;
УдалитьОбработчик Источник.ОбработкаПроведения, ОбработкаПроведенияПоследний;
Если РежимЗаписи = РежимЗаписиДокумента.Запись Или РежимЗаписи = РежимЗаписиДокумента.ОтменаПроведения Тогда
Добавитьобработчик Источник.ПриЗаписи, ПриЗаписиПоследний;
ИначеЕсли РежимЗаписи = РежимЗаписиДокумента.Проведение Тогда
Добавитьобработчик Источник.ОбработкаПроведения, ОбработкаПроведенияПоследний;
КонецЕсли;
КонецПроцедуры
//////////////////////////
Процедура ПриЗаписиПоследний(Источник, Отказ) Экспорт
ПослеЗаписи(Источник, Отказ);
КонецПроцедуры
Процедура ОбработкаПроведенияПоследний(Знач Источник, Знач Отказ, Знач РежимПроведения)
Если Не Отказ Тогда
#Если Сервер И Не Сервер Тогда
Источник = Документы.Документ1.СоздатьДокумент();
#КонецЕсли
Для Каждого НаборДвижений Из Источник.Движения Цикл
#Если Сервер И Не Сервер Тогда
НаборДвижений = РегистрыНакопления.РегистрНакопления1.СоздатьНаборЗаписей();
#КонецЕсли
Если НаборДвижений.Записывать Тогда
НаборДвижений.Записать();
НаборДвижений.Записывать = Ложь;
КонецЕсли;
КонецЦикла;
КонецЕсли;
ПослеЗаписи(Источник, Отказ);
КонецПроцедуры
Процедура ПослеЗаписи(Источник, Отказ)
Если Не Отказ Тогда
ВыполнитьРегистрациюЕслиНадо(Источник);
Попытка
ЗафиксироватьТранзакцию();
ЭтоИнтерактивнаяЗапись = Ложь;
Исключение
ОписаниеОшибки = ОписаниеОшибки();
ЭтоИнтерактивнаяЗапись = Истина;
КонецПопытки;
Источник.ПослеЗаписи();
Если Не ЭтоИнтерактивнаяЗапись Тогда
НачатьТранзакцию();
КонецЕсли;
КонецЕсли;
КонецПроцедуры
// https://its.1c.ru/db/intgr83#content:121:hdoc
Процедура ВыполнитьРегистрациюЕслиНадо(Источник)
#Если Сервер И Не Сервер Тогда
Источник = Справочники.Справочник1.СоздатьЭлемент();
#КонецЕсли
Получатели = Источник.ОбменДанными.Получатели;
Если Получатели.Количество() > 0 Тогда
ПланыОбмена.ЗарегистрироватьИзменения(Получатели, Источник);
Сообщить(СтрШаблон("Регистрация на %1 узлах планов обмена", Получатели.Количество()));
Получатели.Очистить();
Источник.ДополнительныеСвойства.Вставить("ПолучателиОчищены");
ИначеЕсли Источник.ДополнительныеСвойства.Свойство("ПолучателиОчищены") Тогда
ВызватьИсключение "Необходимо заново заполнить получателей объекта или удалить доп. свойство ""ПолучателиОчищены""";
КонецЕсли;
КонецПроцедуры
// Демо подписка
Процедура ДемоПриЗаписи(Источник, Отказ) Экспорт
Сообщить("Подписка Демо ПриЗаписи");
КонецПроцедуры
Теперь вставим в модули объектов обработчик ПослеЗаписи
Процедура ПослеЗаписи() Экспорт
Сообщить("ПослеЗаписи. Транзакция = " + ТранзакцияАктивна());
КонецПроцедуры
Проверка
К статье приложена демонстрационная база с подсистемой СобытиеПослеЗаписи (общий модуль и 2 подписки). Запустив эту базу в обычном клиентском приложении, вы увидите форму с кнопкой "Тест" и формы модифицированных рассмотренным в статье образом справочника и документа. Кнопка "Тест" для выполнит следующий код
ф = Справочники.Справочник1.я.ПолучитьОбъект();
Сообщить(">>> Новая запись справочника");
ф.Записать();
Сообщить(">>> Повторная запись справочника");
ф.Записать();
ф = Справочники.Справочник1.я.ПолучитьОбъект().ПолучитьФорму();
Если ТипЗнч(Ф) = Тип("Форма") Тогда
Сообщить(">>> Новая запись справочника в форме");
ф.ЗаписатьВФорме();
Сообщить(">>> Повторная запись справочника в форме");
ф.ЗаписатьВФорме();
Иначе
Сообщить(">>> Новая запись справочника в форме");
ф.Записать();
Сообщить(">>> Повторная запись справочника в форме");
ф.Записать();
КонецЕсли;
ф = Документы.Документ1.СоздатьДокумент();
ф.Дата = ТекущаяДата();
Сообщить(">>> Новая запись документа");
ф.Записать(РежимЗаписиДокумента.Запись);
Сообщить(">>> Повторная запись документа с проведением");
ф.Записать(РежимЗаписиДокумента.Проведение);
Сообщить(">>> Повторная запись документа с отменой проведения");
ф.Записать(РежимЗаписиДокумента.ОтменаПроведения);
ф = Документы.Документ1.СоздатьДокумент().ПолучитьФорму();
ф.Дата = ТекущаяДата();
Если ТипЗнч(Ф) = Тип("Форма") Тогда
Сообщить(">>> Новая запись документа в форме");
ф.ЗаписатьВФорме(РежимЗаписиДокумента.Запись);
Сообщить(">>> Повторная запись документа с проведением в форме");
ф.ЗаписатьВФорме(РежимЗаписиДокумента.Проведение);
Сообщить(">>> Повторная запись документа с отменой проведения в форме");
ф.ЗаписатьВФорме(РежимЗаписиДокумента.ОтменаПроведения);
Иначе
Сообщить(">>> Новая запись документа в форме");
ф.Записать(РежимЗаписиДокумента.Запись);
Сообщить(">>> Повторная запись документа с проведением в форме");
ф.Записать(РежимЗаписиДокумента.Проведение);
Сообщить(">>> Повторная запись документа с отменой проведения в форме");
ф.Записать(РежимЗаписиДокумента.ОтменаПроведения);
КонецЕсли;
Получим результат:
>>> Новая запись справочника
Подписка1 ПередЗаписью. Динамическое подключение обработчика
ПриЗаписи модуля объекта
ПриЗаписи расширения
ПриЗаписи модуля объекта динамический
Подписка Демо ПриЗаписи
Регистрация на 1 узлах планов обмена
ПослеЗаписи. Транзакция = Нет
>>> Повторная запись справочника
Подписка1 ПередЗаписью. Динамическое подключение обработчика
ПриЗаписи модуля объекта
ПриЗаписи расширения
ПриЗаписи модуля объекта динамический
Подписка Демо ПриЗаписи
Регистрация на 1 узлах планов обмена
ПослеЗаписи. Транзакция = Нет
>>> Новая запись справочника в форме
Подписка1 ПередЗаписью. Динамическое подключение обработчика
ПриЗаписи модуля объекта
ПриЗаписи расширения
ПриЗаписи модуля объекта динамический
Подписка Демо ПриЗаписи
Регистрация на 1 узлах планов обмена
ПослеЗаписи. Транзакция = Да
При записи в форме
>>> Повторная запись справочника в форме
Подписка1 ПередЗаписью. Динамическое подключение обработчика
ПриЗаписи модуля объекта
ПриЗаписи расширения
ПриЗаписи модуля объекта динамический
Подписка Демо ПриЗаписи
Регистрация на 1 узлах планов обмена
ПослеЗаписи. Транзакция = Да
При записи в форме
>>> Новая запись документа
Подписка1 ПередЗаписью. Динамическое подключение обработчика
ПриЗаписи модуля объекта
ПриЗаписи расширения
Подписка Демо ПриЗаписи
Регистрация на 1 узлах планов обмена
ПослеЗаписи. Транзакция = Нет
>>> Повторная запись документа с проведением
Подписка1 ПередЗаписью. Динамическое подключение обработчика
ПриЗаписи модуля объекта
ПриЗаписи расширения
Подписка Демо ПриЗаписи
ОбработкаПроведения модуля объекта
ОбработкаПроведения расширения
Записан регистрРегистрНакопления1
Регистрация на 1 узлах планов обмена
ПослеЗаписи. Транзакция = Нет
>>> Повторная запись документа с отменой проведения
Подписка1 ПередЗаписью. Динамическое подключение обработчика
ОбработкаУдаленияПроведения модуля объекта
Записан регистрРегистрНакопления2
Записан регистрРегистрНакопления1
ПриЗаписи модуля объекта
ПриЗаписи расширения
Подписка Демо ПриЗаписи
Регистрация на 1 узлах планов обмена
ПослеЗаписи. Транзакция = Нет
>>> Новая запись документа в форме
Подписка1 ПередЗаписью. Динамическое подключение обработчика
ПриЗаписи модуля объекта
ПриЗаписи расширения
Подписка Демо ПриЗаписи
Регистрация на 1 узлах планов обмена
ПослеЗаписи. Транзакция = Да
При записи в форме
>>> Повторная запись документа с проведением в форме
Подписка1 ПередЗаписью. Динамическое подключение обработчика
ПриЗаписи модуля объекта
ПриЗаписи расширения
Подписка Демо ПриЗаписи
ОбработкаПроведения модуля объекта
ОбработкаПроведения расширения
Записан регистрРегистрНакопления1
Регистрация на 1 узлах планов обмена
ПослеЗаписи. Транзакция = Да
При записи в форме
>>> Повторная запись документа с отменой проведения в форме
Подписка1 ПередЗаписью. Динамическое подключение обработчика
ОбработкаУдаленияПроведения модуля объекта
Записан регистрРегистрНакопления2
Записан регистрРегистрНакопления1
ПриЗаписи модуля объекта
ПриЗаписи расширения
Подписка Демо ПриЗаписи
Регистрация на 1 узлах планов обмена
ПослеЗаписи. Транзакция = Да
При записи в форме
Вступайте в нашу телеграмм-группу Инфостарт
См. также
Механизмы платформы 1С Разработчик Бесплатно (free)
Разберем 15 мифов о работе платформы «1С:Предприятие 8» – как распространенных, так и малоизвестных. Начнем с классики: «Код, написанный в одну строку, работает быстрее, чем многострочный». Так ли это на самом деле?
16.07.2025 45705 TitanLuchs 109
Работа с интерфейсом WEB-интеграция Механизмы платформы 1С Бесплатно (free)
Веб-интерфейсы повышают качество внешнего вида приложений 1С, предсказуемы с точки зрения верстки, позволяют организовать удобные и высокопроизводительные рабочие места для пользователей. Расскажем об особенностях разработки веб-интерфейсов на React внутри 1С, двустороннем взаимодействии 1С и JavaScript, а также сборке веб-приложения в одностраничный файл.
19.06.2025 18714 zeegin 15
Механизмы платформы 1С Работа с интерфейсом Разработчик Стажер 1С:Предприятие 8 Бесплатно (free)
Про ООП в 1С и о том, как сделать свой код более кратким и выразительным при помощи использования текучего интерфейса (fluent interface).
03.02.2025 26057 bayselonarrend 127
Механизмы платформы 1С Разработчик 1С:Предприятие 8 Бесплатно (free)
В этой статье подробно рассматривается работа с JSON в XDTO в 1С:Предприятие. Вы узнаете, как сериализовать и десериализовать объекты XDTO в JSON, интегрировать 1С с веб-сервисами и API, а также корректно обрабатывать данные при обмене. Разбираются особенности работы с коллекциями, использование функций восстановления и частые ошибки при работе с JSON и XDTO.
30.01.2025 33346 user2122906 10
Механизмы платформы 1С Файловый обмен (TXT, XML, DBF), FTP Разработчик 1С:Предприятие 8 Бесплатно (free)
Этот материал познакомит вас с механизмом XDTO (XML Data Transfer Objects) в 1С и научит эффективно использовать его возможности. Мы разберёмся, как работать с XML-схемами, создавать модели данных, манипулировать объектами XDTO, а также сериализовать и десериализовать их в XML. Вы узнаете, как использовать XDTO для интеграции с внешними системами, избегать типичных ошибок и оптимизировать код. К концу вы будете уверенно применять XDTO для решения сложных задач обмена данными и автоматизации процессов.
17.01.2025 55878 user2122906 13
Механизмы платформы 1С WEB-интеграция Разработчик 1С:Предприятие 8 Бесплатно (free)
В платформе 8.3.27 появилась возможность использовать WebSocket-клиент. Давайте посмотрим, как это все устроено и чем оно нам полезно.
14.01.2025 46843 dsdred 110
Механизмы платформы 1С Разработчик 1С:Предприятие 8 Бесплатно (free)
Особенности "Знач" и разбор документации к нему.
10.01.2025 26480 VAAngelov 60
Механизмы платформы 1С Разработчик Стажер 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)
Эта небольшая статья - некоторого рода шпаргалка по файловым потокам: как и зачем с ними работать, какие преимущества это дает.
23.06.2024 40486 bayselonarrend 24
Да и дописывать такое в типовые модули не очень хотелось бы.
Есть другой вопрос-предложение. Ты не смотрел в сторону "МенеджерИсторииДанных" и события "ОбработкаПослеЗаписиВерсийИсторииДанных"? Там есть настоящее событие "ПослеЗаписи", которое еще и отрабатывает вне основной транзакции, а это огромный плюс для такого события.
Документация здесь
Там смысл в том, что надо добавить "ОбработкаПослеЗаписиВерсийИсторииДанных" в модуль менеджера объекта, которое срабатывает при вызове "ИсторияДанных.ОбновитьИсторию()" или "ИсторияДанных.ВыполнитьОбработкуПослеЗаписиВерсий()". Обновление истории обычно вешают в отдельное рег задание.
1. Этот обработчик доступен только в режиме совместимости 8.3.15
2. Он вызывается только если у объекта метаданных включено ведение истории данных, т.е. уже не универсально.
3. Выполнил запись в файловой базе при включенных флажках "Обновлять историю..." и "Выполнять обработку после записи..". Обработчик не вызывался, т.е. вызывается он только при явном запуске обновления версий, что опять же не универсально.
3. И у него кажется много других ограничений, например
Исключение в обработчике приводит к прерыванию выполнения обработки остальных версий в очереди, поэтому рекомендуется не допускать возникновения исключений.
Подписки всегда выполняются ДО обработчика в модуле. Расширения обработчика ПриЗаписи также будут вызваны до выполнения динамически подключенного обработчика. Так что схема полностью надежна. Обновил демо базу - добавил расширения для всех обработчиков модуля объекта с выводом сообщений для наглядности отслеживания порядка выполнения обработчиков.
>>> ПриЗаписи Я
ПриЗаписи расширения
ПослеЗаписи
>>> ПриЗаписи Документ1 000000016 от 04.04.2023 8:42:08
ПриЗаписи расширения
ПослеЗаписи
>>> ПриЗаписи Документ1 000000016 от 04.04.2023 8:42:08
ПриЗаписи расширения
ОбработкаПроведения
ОбработкаПроведения расширения
ПослеЗаписи Показатьтут другая подстава ожидает.
Подписки выполняются в очередности как они отображаются в дереве метаданных. И то - это не гарантированно.
Т.е. если ты сейчас сделаешь подписку, а потом с обновлением прилетит новая подписка, то твоя уже не будет видеть изменений, которые сделала новая подписка.
Ну или кто-нибудь банально отсортирует подписки по алфавиту. У меня такое уже было (
| Код |
|---|
Процедура ОбработкаПослеЗаписиВерсийИсторииДанных(инфоОЗаписиВерсии) Экспорт
Для Каждого записьИстории Из инфоОЗаписиВерсии Цикл
ЗаписьЖурналаРегистрации(
"СобытиеПослеЗаписи",
УровеньЖурналаРегистрации.Предупреждение,
,
,
"ХХХ ПослеЗаписи: " + записьИстории.Данные
);
ИсторияДанных.УдалитьИзОбработкиПослеЗаписиВерсий(записьИстории.Данные, записьИстории.НомерВерсии);
КонецЦикла;
КонецПроцедуры
Показать полностью |
Также он более затратный, т.к. требует считывания как минимум самого объекта из базы заново, а может еще и связанных данных, которые уже были в ДополнительныеСвойства в моей реализации.
Может ты не установил свойство "Обновлять историю данных сразу после записи"?
Про ДопСвойства и ОбменДанными вообще не понял. Зачем они в "ПослеЗаписи"?
Обычно "ПослеЗаписи" нужно как раз для того, чтобы сделать постобработку ВНЕ основной транзакции, которая, как правило, и так слишком длинная. Например, для того, чтобы отправить измененные объекты в какой-то свой супер-обмен.
Т.е. я в свое время наоборот искал то, что бы отрабатывало после записи и никак не влияло на основную логику: ни временем, ни тем более своими ошибками
Но, опять же, нужно отталкиваться от задачи.
Чаще всего ПослеЗаписи нужно для того, чтобы отправить измененные объекты в обмен. Для этого по классической схеме делают РС, в который пихают ссылки на измененные объекты в ПриЗаписи и потом делают его постобработку. Или примерно тоже самое через ПланыОбмена.
Здесь же не нужно вообще никак встраиваться в ПриЗаписи, что гарантирует нам, что основная логика не нарушится и время на транзакцию никак не увеличится. Плюс не надо городить и поддерживать доп. объекты метаданных.
Ну и не менее важное - весь типовой код (если конфа на поддержке), останется девственным. Ведь обработчик "ПослеЗаписи" можно добавить через свою подписку:
В подписках на события проверяется нужна ли доп.обработка и нужное событие фиксируется в очереди на обработку.
Далее регламентным заданием эта очередь обрабатывается и выполняются нужные действия.
Мне не нужно делать моментальную обработку событий, поэтому регл.задание вполне подходит.
Зато сама обработка события никак не тормозит основную работу программы в момент записи/проведения.
Ну и работой через алгоритмы я добиваюсь того что мне не нужно ничего менять в расширениях и в конфигурации чтобы изменить алгоритм обработки или добавить обработку нового события.
Конфигурация своя собственная, т.е. никаких проблем с внедрением подобного механизма нет.
А вот клиенты, которые используют мою конфу, имеют своих сисадминов и программистов и им нет необходимости конфу/расширения править, они просто нужные алгоритмы добавляют в справочник.
Вообще приходится много где использовать обычные скрипты или алгоритмы из ИР, чтобы расширить возможности настройки программы.
Работает следующим образом:
// Заимствуем документ или справочник в расширении и пишем одну единственную строчку в модуле объекта:
Обработки._СобытияОбъектов.СобытиеПослеЗаписи(ЭтотОбъект, "ОбщийМодуль1.Документ1_ПослеЗаписи", "Тест");
Из неё понятно какая процедура и откуда будет вызвана и с каким параметром После Записи. В общем модуле или любом другом месте пишем свою реализацию алгоритма. Можно сделать единственную точку входа для всех объектов подписанных таким образом, а потом проверять тип.
Подписки выполняются после основного кода
...Сначала отрабатывается событие в самом объекте и вызывается обработчик события, определенный в модуле объекта или набора записей..
... Затем в произвольном порядке вызываются внешние обработчики, назначенные для данного события.
Мне кажется замудренным такой способ решения задачи, поскольку изначальную постановку задачи не знаю.
Но для общего случая - это замудренный способ.
В одном проекте - специально посмотрел сейчас - использую процедуру ОбработкаПроведения() в качестве отсутствующей процедуры ПослеЗаписи() - изменяю статус заказа покупателя (храню статус в регистре сведений) + формирую csv, выгружаю на фтп для сайта. Лет 10 назад сделал - работает. Были прерывания транзакции - когда я днем всех отрубал от 1с для обновления - статус заказа "отгружен" и файл ушел на сайт - при прерывании транзакции статус откатывается, а файл уже не вернуть, или статус = отгружен, а файл не прилетел на фтп... Но это все редкие случаи, решаются все равно через менеджера - менеджер готовит заказы - заказ перепроводится.... Не стал усложнять алгоритмы - поток пока такой, что ошибок не возникает.
Второй проект - тоже открыл специально - в процедуре ПередЗаписью() записываю свой реквизит объекта "Зарегистрирован", хотя регистрация в плане обмена происходит в следующей процедуре ПриЗаписи(). Здесь есть допущение, что транзакция не прервется между процедурами ПередЗаписью() и ПриЗаписи().
За несколько лет не было случаев прерывания транзакций:
Если Не Отказ И Зарегистрирован Тогда
//регистрирую в процедуре ПриЗаписи()....
Здесь переменная "Зарегистрирован" это аналог ДополнительныхСвойств для разделения логики алгоритма, но у меня была возможность создать реквизит в документе и не использовать ДопСвойства.
Вообще , судя по тому что из процедуры в процедуру, связанных с записью объекта переходит параметр Отказ, для своей логики надо также протаскивать какой-нибудь параметр - что и реализовано с помощью ДопСвойств объекта.
Очень часто приходится использовать ДопСвойства, чтобы передать информацию из одной процедуры в другую (речь о процедурах ПередЗаписью, ПриЗаписи, ОбработкаПроведения, подписки на события, связанные с этими же процедурами).
(0) Я так понимаю, вы решаете задачи связанные с адресным хранением - там конечно замудрено - видел я разные технологии и все почти недоделанные - в адресном хранении все процессы движутся только вперед - откатить назад или задним числом нереально проводить, поскольку документы связаны с другими документами. Наглядный пример Есть Реализация, но отгрузка товаров через РасходныйОрдер, а он в свою очередь зависит от нескольких статусов Отобран и Отгружен. На каждый момент времени (на каждую секунду) проверяется наличие товара в ячейке.
Может быть не убедительно написал, но при возникновении ошибок - в середине дня вылетает сервер - потом весь день ковыряешься, и легче удалить все документы и заново на компе (но не на ТСД) вручную провести все отгрузки в режиме План=Факт...
Сложно описал....Но как бы не прописывались отмены транзакций в адресном хранении - они корректно не откатывают....Вот я такое видел...Как говорится, не все конфы видел, с Акселот не работал...
...я видел вашу "постановку"... у нас же не олимпиада по 1с-программированию...
я имел в виду, что хотел бы услышать предметную из реальной жизни задачу.. и понять для начала почему ее нельзя решить имеющимися платформенными механизмами...
у меня два или три проекта были - просили то же самое, только на основании Заказа покупателя, ПоступленияТоваров, ПеремещенияТоваров... Я пробовал как вы - в обработке проведения создавать документ - но на чем-то застопорился (не помню). Теперь подобные задачи делаю просто - расширяю документы-регистраторы регистра ЦеныНоменклатуры - добавляю нужный документ (Заказ, Поступление, Перемещение) и делаю движения напрямую в регистр сведений ЦеныНоменклатуры.
Использовать регл. или фоновые задания - я не предлагал - тем более по вашей задаче - их использовать не получится.
Если нужно, могу глубже окунуться в вашу задачу и реализовать простым способом в ходе обсуждения.
В этом случае делают немедленный запуск процедуры формирования нужных вам записей в регистре в момент печати. Из очереди ес-но его тоже надо будет удалить.
Либо при печати просто принудительно стартовать нужное рег задание.
Или между созданием документа и стартом рег задания успели закрыть месяц? ))
Чистов на экзамене по платформе поставил за такое решение 2 балла (не мне). Хотя сами разработчики такими решениями блещут часто, например, при определенных настройках (вполне себе так сказать валидных) в УХе при проведении ПТУ создаётся(если нет) и проводится документ ОФД, а за ними ещё изменяется и перепроводится документ ВСКД... Привет бухгалтеру проводящему закрытие месяца с восстановлением последовательности.
Но надо такого избегать конечно же.
Причём писал УХашникам не раз про эту проблему. В каждом релизе вплоть до 3.1.16.5 вставляли доп. свойство при проведение из закрытия месяца, чтобы все вышеописанные документы не дёргались, а проводилась только ПТУ. Но тщетно...
(60)
Просто как избежать если поставщик такое вытворяет? Не переписывать же целых 4 блока. Этаж анриал снимать с поддержки такой пласт механизмов. (БУ-НУ-ОУ-БЮДЖЕТ). Вот и ставим костыли в каждый релиз...
Ещё в ЕРПУХе не смотрел, но что то мне подсказывает что там всё то же самое.
я имел ввиду, что надо избегать тем, кто делает что-то своё. Типовое, конечно же, лучше не трогать. Очень дорого выйдет
- полностью переделал механизм
- учел порядок вызова и наличие множественных подписок
- учел авторегистрацию в планах обмена
- обновил демобазу и в частности расширил тест для проверки всех возможных ситуаций
- указал в начале пример применения события
а как устроена "очередь"?
вот у меня пример: очередь устроена в виде регистра сведений - есть колонка (поле) приоритет. Если я запускаю групповую обработку, то документы попадают в очередь с приоритетом 2, если менеджер формирует документ, то он попадает в очередь с приоритетом 0, есть случаи когда документы садятся в очередь с приоритетом 1.
при этом регл. задание каждые N минут обрабатывает очередь - берет первые M документов в порядке возрастания приоритета (0 - самый первый, 2 - самый последний) и обрабатывает документы.
то есть за "оперативный запуск" отвечает "приоритет" в очереди.
У тебя гарантированная оперативность выполнения фонового задания обработки очереди не менее N минут. А с обработчиком ПослеЗаписи она может быть 0 секунд. Например я записал какой то особо важный документ и хочу опционально сразу его обработать в той очереди. Для этого мне без события ПослеЗаписи надо из транзакции записи вызывать запуск фонового задания. А с событием ПослеЗаписи - я его запущу вне транзакции.
можно два регл. задания создать - первое мониторит очередь с приоритетом 0 - каждые 15-30 сек (в зав. от скорости выполнения обработки одного документа), второе рег. задание - мониторит очередь с приоритетом 1 и 2 каждые N минут.
но если надо прям сразу - то я бы дальше призадумался - "может и в очередь не надо помещать?" - сразу вызвать процедуру обработки после строки кода , где происходит запись документа (объекта). То есть локализовать вызов записи док-а (объекта) и сразу прописать после него вызов обработки без помещения в очередь....
Вопрос. Не за компом, так бы сам проверил.
Что будет, если наш объект, внутри которого мы создаём платформенный обработчик "ПослеЗаписи" не завершит транзакцию? То есть, пресловутый "красный крест" в рантайме? Отмена транзакции из-за ожидания на блокировке или нехватке прав. Наш обработчик выполнится или все-таки нет? Ты просто пишешь про некую "очередь", а добавление в неё синхронное или нет? И если асинхронное, то может ты нашёл способ обойти "красный крест", сам того не подозревая???
Хотя раз мы там фиксируем неявную транзакцию, значит это тот же самый синхронный поток - значит не выполнится наш добавленный обработчик при выбросе исключения...?
Или нам достаточно просто Отказ вернуть в Ложь. Иначе говоря: значение Отказ проверяется в момент окончания транзакции в НАШЕМ новом обработчике или оно уже проверено к моменту попадания к НАМ и транзакция по факту уже откачена?
Технически это возможно, но с большой вероятностью нарушит корректную бизнес-логики.
Предлагаемая в этой статье методика не меняет логику работы параметра Отказ. Если он включен, то предлагаемый код просто не выполнится как, т.к. экранирован условием "Если НЕ Отказ Тогда".
Добавили РС Блокировки с измерением УИД.
В самом конце последнего ПослеЗаписи ставим блокировку на этот РС по рандомному УИДу.
Затем запускаем фоновое задание, которое начинает транзакцию и пытается поставить свою блокировку по тому же УИДу.
Как только блокировка успешно установится - родительская транзакция завершилась и можно выполнять действия после записи.
Этот метод более затратен по ресурсам, зато не "ломает" нормальную логику ПослеЗаписи.
Поэтому явное досрочное завершение транзакции не даст в ней выполнится коду платформы, который выполняет регистрацию на узлах планов обмена. Значит нужно сделать это опять же явно. При этом еще и надо сделать так, чтобы при второй (фиктивной) транзакции эта регистрация не повторилась платформой, чтобы не было двойной работы.
Как я писал выше, у платформы уже есть собственный "ПослеЗаписи". Его и нужно использовать в таких случаях. ИМХО, конечно.
Насколько я понял, ты просто регистрируешь объекты к обмену в плане обмена. Для этого вполне достаточно указанной ссылки на объект в БД.
Ну и для меня (как и для любой нагруженной системы) самая важная борьба - это борьба за сокращение времени транзакции записи-проведения.
1. Учел интерактивные транзакции, т.е. запись из формы объекта. В них красивого решения не нашел, поэтому оставил выполнение обработчика в транзакции.
2. Добавил запись движений документа при явном завершении транзакции проведения документа.
3. Добавил абзац по событие ОбработкаПослеЗаписиВерсийИсторииДанных
По-моему он просто работает, если версия платформы 8.3.15 и выше.
Мне механизм рассмотренный в статье подходит идеально. Даже постановкой задачи. Выполнить обработку данных связанных с объектом после его записи, но вне транзакции.
Единственный обнаруженный минус ломается логика работы обработчика ПриЗаписи из модуля формы. Решается переносом логики в общий модуль процедура ПриЗаписи до первой фиксации транзакции (у меня как оказалось там нет ни чего связанного с формой).
Вы можете заказать платную консультацию или разработку у автора. Будет создан приватный заказ на «Бирже заказов» для автора.
№ 1838612
Создание 03.04.23 11:00
Обновление 20.02.25 14:56
Просмотры 14270
Загрузки 64
Рейтинг
55
Комментарии 70
Код открыт Да
Рубрики Механизмы платформы 1С
Кому Разработчик
Тип файла Архив с данными
Платформа 1С:Предприятие 8
Конфигурация Универсальные
Операционная система Не имеет значения
Страна Не имеет значения
Отрасль Не имеет значения
Налоги Не имеет значения
Вид учета Не имеет значения
Доступ к файлу Бесплатно (free)