Вопрос

Есть БП который вызывается через кнопку в клиентском модуле, он заполняет деталь. Как через сообщения сделать обновление детали после окончания работы БП что бы было видно наполнение детали? На форуме был такой вопрос но там было сделано через ивент в БП старого типа, в новых это не работает.

Я понимаю что нужно создать в конце БП скрипт который будет генерировать сообщение, а на клиентском модуле нужно подписать на него, но видимо я делаю что-то не так и у меня не работают мои попытки 

У меня такой же вопрос

7 комментариев
Лучший ответ
PostMessage отправляет конкретному юзеру. Поэтому надо быть уверенным, что бп запущен от нужного пользователя и он на нужной странице(где есть код для обработки обратного сигнала). 
Если не подходит, можно воспользоваться PostMessageToAll(string sender, string message). Рассылает сообщение по всей конфигурации всем пользователям.

Здравствуйте!

В конце БП в элементе Задание-сценарий вставляете следующую строку:
 

MsgChannelUtilities.PostMessage(UserConnection, "MyMessage", "UpdateDetail");

В клиентском модуле детали реализовать следующий код:
 

init: function () {
				this.callParent(arguments);
				this.subscriptionFunction();
			},
subscriptionFunction: function() {
				Terrasoft.ServerChannel.on(Terrasoft.EventName.ON_MESSAGE,
				this.bpListenerMessage, this);
			},
bpListenerMessage: function(scope, message) {
				if (!message || message.Header.Sender !== "MyMessage") {
					return;
				}
				var message2 = message.Body;
				if (!this.Ext.isEmpty(message2) && message2 === "UpdateDetail") {
					this.updateDetail();
				}
			}

Примерно так.

Нигрескул Алексей,

 

Не обновляет, уже и не знаю в чем дело может быть

В БП

var userConnection = Get<UserConnection>("UserConnection");
Terrasoft.Configuration.MsgChannelUtilities.PostMessage(userConnection, "ReloadDetailConcert", "UpdateDetail");
return true;

На клиенте

init: function () {
	this.callParent(arguments);
	this.subscriptionFunction();
},
subscriptionFunction: function() {
	Terrasoft.ServerChannel.on(Terrasoft.EventName.ON_MESSAGE,
	this.bpListenerMessage, this);
},
bpListenerMessage: function(scope, message) {
	if (!message || message.Header.Sender !== "ReloadDetailConcert") {
		return;
	}
	var message2 = message.Body;
	if (!this.Ext.isEmpty(message2) && message2 === "UpdateDetail") {
		this.updateDetail();
	}
},

 

PostMessage отправляет конкретному юзеру. Поэтому надо быть уверенным, что бп запущен от нужного пользователя и он на нужной странице(где есть код для обработки обратного сигнала). 
Если не подходит, можно воспользоваться PostMessageToAll(string sender, string message). Рассылает сообщение по всей конфигурации всем пользователям.

Варфоломеев Данила,

Изменил на 

Terrasoft.Configuration.MsgChannelUtilities.PostMessageToAll("ReloadDetailConcert", "UpdateDetail");
return true;

не помогло

Нужно ли еще прописать?

messages: {
	"ReloadDetailConcert": {
		mode: Terrasoft.MessageMode.BROADCAST,
		"direction": Terrasoft.MessageDirectionType.SUBSCRIBE
	}
},

 

Prime Source,

Да нет. Должно и так работать. Даже subscriptionFunction не вызывается?

Варфоломеев Данила,

По дебагу срабатывает, и сообщение правильно ловит, и выполняет this.updateDetail(); ,но почему нет данных в детали не пойму. Может что в процессе не так? Вот его скрин, там идет цикл который делает 8 проходов, и когда в таблице 8 записей становится он выполняет скрипт сообщения и завершает

 

Prime Source,

//Relationships - название детали из details.
//пример:
this.updateDetail({detail: "Relationships"});

Проверьте код(указывается ли имя детали). Плюс должны быть настроены колонки

Войдите или зарегистрируйтесь, чтобы комментировать
Публикация

Вопрос:

Каким образом можно отправить email сообщение из бизнес-процесса с вложенными файлами?

Кейс такой: Есть раздел "Контрагенты", в нем есть деталь Файлы и ссылки, в данную деталь добавляю 2 файла.
Как только статус контрагента перейдет, допустим, в "Отправка", запускается процесс отправки письма с вложенными файлами из детали Файлы и ссылки. Кроме того, email будет отправляться вручную, после запуска бп, контакту текущего пользователя будет появляться сформированное письмо для выбора адресата (контакты контрагента).

Ответ:

Для Вашей задачи можно воспользоваться следующим подходом:
- Создать активность с типом email
- Добавить для нее вложение, например, открыв страницу редактирования пользователю и прикрепив нужные файлы
- Установить с помощью элемента Формула значение для параметра paractivityid
- В рамках задания сценария выполнить отправку:
var activityId = Get<Guid>("paractivityid");
var emailClientFactory = ClassFactory.Get(new ConstructorArgument("userConnection", UserConnection));
var activityEmailSender = new ActivityEmailSender(emailClientFactory, UserConnection);
activityEmailSender.Send(activityId);
return true;

При этом необходимо в usings добавить следующие библиотеки:
- Terrasoft.Mail.Sender
- Terrasoft.Mail
- Terrasoft.Core.Factories
- Terrasoft.Configuration

Пример использования данного кода можно найти в базовом процессе "Отправка email сообщения контакту обращения".
 

Поделиться

1 комментарий

Добрый день Ксения.

Вариантов реализации данной задачу очень много. Но если нам требуется отправить Емайл с фложениями, я бы пошел по пути создания своего Элемента процесса, вывода его в "Элементы процесса" и далее его бы использовал для выполнения своих Кейсов. Если внимательно на это посмотреть, то элемент "Отправить email" практические все это умеет и даже есть вставить C# код по событию "После сохранения активности" для пост обработки.

я бы взял за основу данных Элемент процесса и переделал под себя.

Войдите или зарегистрируйтесь, чтобы комментировать
Публикация

Вопрос:

Как отправить уведомление через элемент процесса Добавить данные. Элемент Notification с типом Remindingотрабатывает, но уведомление не приходит.

Ответ:

Проблема связана с настройками элемента "Добавить данные". Для корректного добавления уведомления Вам необходимо добавить маппинг поля "Объект" на объект, по которому Вы хотите добавить уведомление. Пример заполнения настроек:

Объект: [#Справочник.Объект раздела (представление).Activity#]
Источник: объект, с которым должно быть создано напоминание ( к примеру, продажа)
Уникальный идентификатор записи: id записи источника

В рамках бизнес-процесса есть возможность создавать уведомление по новому разделу, для этого Вам необходимо в справочнике "Источник уведомления" создать новую запись для Вашего раздела и указать её в настройках элемента (если в разделе Справочники не будет указанного, необходимо его создать).

Но при отправке уведомления по своему разделу не будет увеличиваться и обновляться счетчик новых уведомлений, это связано с тем, что для нового раздела не настроен провайдер.
Для создания провайдера потребуется определенный навык в разработке, Вы можете ознакомитсья с реализацией базовых провайдеров в исходных кодах LeadNotificationProvider, использующего INotificationProvider.

В качестве обходного решения Вы можете создавать Активность (например, проконтролировать обработку записи из кастомного раздела № Х.), и создавать в рамках процесса напоминание по Активности:


В данном варианте в элементе "Уникальный идентификатор записи" необходимо выполнить маппинг на id из элемента "Читать данные Активности".

Либо же Вы можете включить визирование в разделе и отправлять визу по созданной записи, детальнее в статье на Академии.

 

Поделиться

0 комментариев
Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Добрый день.

Подскажите пожалуйста как выбрать из объекта бизнес-процесса "Изменение данных" уникальные поля записей, которые были изменены? 

Есть объект Акции и Партнеры. У акции есть справочное поле с типом акции. Есть бизнес-процесс, который по определённому алгоритму изменяет акции. Изменение акций выполняется  через элемент "Изменить данные".

Как мнем выбрать уникальные типы акции, которые были изменены?

У меня такой же вопрос

4 комментария
Лучший ответ

Можно делать не массовое изменение, а читать еще неизмененные, их изменять, индивидуально делать доп.действия, читать следующие неизмененные и т.п.

Второй вариант - сделать БП, который реагирует на изменение акции

Третий вариант - дождаться обещанного массового запуска подпроцессов, который будет в одной из следующих версий :)

Можно делать не массовое изменение, а читать еще неизмененные, их изменять, индивидуально делать доп.действия, читать следующие неизмененные и т.п.

Второй вариант - сделать БП, который реагирует на изменение акции

Третий вариант - дождаться обещанного массового запуска подпроцессов, который будет в одной из следующих версий :)

Если по разделу настроен журнал изменений, то там видно, кто когда в какой записи менял поле. Вся информация в журнале хранится в служебных таблицах той же базы. Теоретически, можно анализировать записи оттуда.

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

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

Спасибо за участие. Я придумал решение. Я просто после изменения Акций делаю запросы на чтение данных по условиям нужных мнем типов акций, и по результату запросов запускаю подпроцесс с параметром этого типа Акции.

Войдите или зарегистрируйтесь, чтобы комментировать
Публикация

Вопрос: 

Какой бизнес процесс обеспечивает рассылку е-майл сообщений?

Ответ:

Если Вас интересует функционал маркетинга, в базовой версии рассылки email-сообщений для компаний выполняются с помощью отдельного функционала рассылок. Подробно он описан на Академии: https://academy.terrasoft.ru/documents/marketing/7-9/kak-rabotat-s-massovymi-rassylkami

Если же Вас интересует настройка бизнес-процесса, то для выполенения рассылки Вы можете использовать элемент "Отправить email". Работа элемента описана по ссылке: https://academy.terrasoft.ru/documents/technic-bpms/7-10/element-processa-otpravit-email

Поделиться

0 комментариев
Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Добрый день!

Необходимо отправлять email-оповещение при назначении обращения по шаблону из справочника.

Сообщение из раздела обращений которое нужно прочитать:

Upd. Процессом считывания данных и заполнением шаблона занимается бизнес-процесс "SendEmailToSROwner", пакет "CaseService". 

Есть ли возможность вытащить из ленты в бизнес-процессе последнее сообщение?

У меня такой же вопрос

2 комментария
Лучший ответ

Те как написал Саша, в БП через элемент чтения данных только отсортируй их по убыванию даты создания.

Лента — это обычный объект ESNNotification и связанный с ним SocialMessage. Можно читать стандартными элементами чтения данных.

Те как написал Саша, в БП через элемент чтения данных только отсортируй их по убыванию даты создания.

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Можно ли как-то прочитать название если в объекте в колонке указан справочник, так как там указан Guid?

Пример:

[#Читать данные контакта.Первый элемент результирующей коллекции.Страна#] узнать название страны при чтении из "Читать данные"

У меня такой же вопрос

8 комментариев
Лучший ответ

Здравствуйте!

Можно получить нужное вам значение 2 вариантами.

1. Первый способ - 2-мя элементами 'Чтение данных'. Одним вычитываете Id города из Вашего объекта, а вторым название города по его Id из предыдущего элемента.

2. Второй способ сразу вычитать данные в элементе скрипт таск с помощью EntitySchemaQuery.

Здравствуйте!

Можно получить нужное вам значение 2 вариантами.

1. Первый способ - 2-мя элементами 'Чтение данных'. Одним вычитываете Id города из Вашего объекта, а вторым название города по его Id из предыдущего элемента.

2. Второй способ сразу вычитать данные в элементе скрипт таск с помощью EntitySchemaQuery.

Алла Савельева,

Первый способ не подходит, там 18 справочником, выйдет многовато читать. Второй способ я использовал, но руководство не совсем приветствует использование C# скриптов

Придётся делать подряд 2 элемента чтения данных: в первом читать из контакта Id страны, во втором — из справочника стран, отфильтрованного по этому Id, получать название.

Зверев Александр у меня 6 таблиц которые нужно заполнить данными. Для каждой таблицы порядка 20 справочников читать. Выйдет адский труд

Если таких слишком много и писать скрипты не хотите, можно ещё сделать view с текстовыми колонками, потом создать по нему объект и работать с ним.

Prime Source,

Prime Source пишет:
руководство не совсем приветствует использование C# скриптов

Главное с этим не злоупотреблять, в данном случае это оптимальный вариант.

К сожалению, пока вычитать данные из связанных таблиц в элементе 'Чтение данных' невозможно.

Как вариант, можно реализовать представление, которое содержит все нужные данные и обращаться к нему из элемента 'Чтение данных', но это такой вариант костыля и потом, так как мне не до конца известна Ваша задача, то не факт, что представление будет лучше, чем C# код.

Алла Савельева,

Спасибо, мне нужно было что бы люди тоже подтвердили мое мнение начальству. Скрипт я написал, он сам чиатет и сам пишет все в таблице трансферную которую мне нужно

Если хотите правильнее всего и много однотипных чтений, создайте своё действие в процессе (отдельную схему с этой всей логикой внутри) и далее используйте в БП без необходимости программирования.

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Добрый день!

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

У меня такой же вопрос

4 комментария
Лучший ответ

нет, точнее так:

1. Если запускаете из пользовательского интерфейса - там только на запуск, нельзя отследить окончание выполнения.

2. Если есть преднастроенные страницы (кастомные), то можно в них последовательно включать и выключать маску.

3. Никто не помешает пользователю нажать рефреш :)

нет, точнее так:

1. Если запускаете из пользовательского интерфейса - там только на запуск, нельзя отследить окончание выполнения.

2. Если есть преднастроенные страницы (кастомные), то можно в них последовательно включать и выключать маску.

3. Никто не помешает пользователю нажать рефреш :)

Дмитрий Степанов,

Дмитрий, добрый день!
Спасибо за предложенные варианты.
Мне не совсем они подходят, возможно я не совсем точно описал кейс.
Кейс состоит в том, что:
последовательно выполняются три подпроцесса:
1) Первый заканчивается

преднастроенной страницей, далее идет переход во 2-й подпроцесс

2) Второй подпроцесс без страниц, и он выполняется достаточно долго(порядка 10 сек). В это время отображается единое окно и пользователь может быть сбит с толку.

3) После выполнения 2-го процесса запускается 3-й процесс с преднастроенной страницей. 

Вопрос в том, чтобы как-то залочить экран пользователя, чтобы перед поднятием страницы в 3-м процессе он во время временного окна никуда не перешел из единого окна.

Подозреваю, что полностью оградить от действий пользователя никак не получится, ведь он всегда сможет открыть второй браузер или анонимное окно. Разве что банить на несколько минут.

В описанном примере можно попробовать так: одновременно с запуском длительного фонового процесса показать ещё одну преднастроенную страницу без всяких элементов управления, но с поясняющей надписью или картинкой, а логику её закрытия реализовать путём отправки из процесса сообщения по Websocket.

 

Зверев Александр,

Александр, спасибо за идею. Похоже на самый реалистичный вариант.

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Добрый день! 

Возникла проблема с обработкой ответа в массиве, при вызове веб-сервиса через стандартный элемент в бизнес-процессе.

В настройках раздела "Веб-сервисы" есть деталь "Методы сервиса", при настройке обработки ответа, есть поле "Является массивом", при его активации, в бизнес-процессе возможность записать данный ответ в параметр БП для дальнейшей обработки представляет возможным только с типом данных "Коллекция значений с атрибутами", и соответственно разобрать это можно только с помощью "Задания-сценарий"

Пример настройки ответа:
 

Вопрос, как разобрать обработанный ответ?

Как я понял, нужно обращаться к ICompositeObjectList, но совсем не понятно, как это работает...

Пример ответа (Для каждого контакта поля в выборке id, name, phone):

 

 

У меня такой же вопрос

7 комментариев

Вам нужен пример, как эти данные в коде обработать?

Если бы результат всегда возвращал одну запись в массиве, парсинг  можно было бы организовать при настройке параметров. Плюс у Вас ещё и элементы массива тоже, по сути, являются записями с 4 полями. Можно ещё попробовать считать всё внутри квадратных скобок в одну большую текстовую переменную, а потом разбирать программно в скрипте, наполняя массив или список объектов с полями. В 7.13 обещают изменения в движке веб-сервисов, возможно, стоит чуть подождать и он сможет и такое автоматически разобрать, как минимум, до массива строк.

Литвинко Павел,
Да. А если ещё конкретнее, то пример, как разобрать массив уже "обработанный" стандартными возможностями обработки ответа (первый скрин).

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

По скольку в академии этот вопрос "опущен", но такая необходимость возникает. Сейчас в стандартном поле "Ответ сервиса" непонятный html документ вываливается, даже без данного массива, но HTTP ответ 200

Зверев Александр,

если бы одну, то проблем бы конечно было меньше, но интересует выборка большого кол-ва данных

да, тоже такого варианта придерживаюсь "Можно ещё попробовать считать всё внутри квадратных скобок в одну большую текстовую переменную, а потом разбирать программно в скрипте"

Но, сейчас в ответе сервиса html документ без данного ответа но с кодом 200, и также интересно, что же все таки возвращает эта настройка обработки ответа, та, что на первом скрине

Посмотреть, что вообще пришло в ответ, можно в Fiddler (если сайт поднят локально). Может, что-то изменилось и во входящих параметрах и возвращаемый массив стал пустым?

Зверев Александр,

Действительно, пересобрал сейчас - заработало, видимо что-то пропустил)
То есть Fiddler должен вернуть обработанный ответ? 

Плясать от ответа сервиса(как на втором скрине) - в принципе не самое худшее, но для чего тогда сделали "Является массивом", при том, что ответ сервера пересобирается в таком случае в неведомый интерфейс IObjectList который можно записать в параметр "Коллекция значений" и уже исходя из него что-то делать...

https://academy.terrasoft.ru/api/netcoreapi/7.12.0/Terrasoft.Common~Ter…

 

Fiddler позволяет посмотреть, какие запросы и ответы ходили по HTTP.

В 7.13 эту коллекцию можно будет обработать в интерфейсе, там доработали возможность для ответов-массивов. Документация должна появиться после релиза. В 7.12, где эта галочка впервые появилась, — только кодом, но готовых примеров тоже нет. Также, сомневаюсь, что любая автоматизация сумеет разобрать строку на 4 поля по разделителям вроде «Phone: » (разве что делать элементами-формулами), так что перебирать в скрипте всё равно потребуется.

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Добрый день, Коллеги!

Часто сталкиваемся с проблемой того, что при активном окне процесса, нельзя запускать БП поверх них, они будут выполнятся в фоне. Приходить писать код, который будет выполнять определенные действия, например, создавать запись в разделе из кнопки.

Реальный, частый кейс:

Пользователю открывается задача по БП с текстом: "Оформите счет и договор по заказу", в системе есть 2 стандартных бп, которые это делают, но, когда пользователь прямо из задачи по ссылке переходит к заказу и через действия пытается это сделать, ничего не происходит (он так думает), но на самом деле процессы то запускаются, просто в фоне...

Очень хотелось бы иметь возможность в конструкторе бп установить признак для процесса "Запускать поверх других процессов". В данном случае у пользователя запускался процесс создание счета и договора.

У меня такой же вопрос

9 комментариев

А если и у второго процесса галка стоит, что делать? Ещё одну настройку добавлять, «Запускать поверх вообще всех процессов»?

В таких случаях будет лучше переработать логику процессов: либо отключить стандартные и интегрировать их логику в свой процесс, либо разбить свой на несколько отдельных частей, которые завершаются поочерёдно.

Зверев Александр,

Нет, достаточно одной галки, она будет означать, что этот процесс начинается поверх любого другого. Вопрос не в ходе процесса, а в его начале-старте.
Вы не поняли сути проблемы. Проблема заключается в том, что человеку ставится задача, создать заказ из продажи или создать счет из заказа и ему удобнее прямо из задачи перейти в продажу или заказ и нажать кнопку, которая запустит другой процесс, процесс создания заказа или счета. Ему неудобно нажимать сохранить (в задаче), ждать когда его вернет система на последнюю карточку, открывать расписание, находить задачу, переходить по ссылке и нажимать на кнопку создать заказа или счет. Прочувствуйте разницу во времени, предложите альтернативу. Какие тут изменения в процессе, нам нужно запустить бп, чтобы он не в фоне начался.

П.С. Я не говорю про вариант подвязывания скрипта для кнопки создания продажи или счета.

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

Вы, наверно, меня не понимаете. Даже если это мелкий подпроцесс с 1 задачей, он все равно не позволит запустить процесс сверху.Думаю, Вы с таким не сталкивались, а у нас это не каждый второй процесс, каждый первый. Нам приходит каждый раз делать кодом действия из кнопки. Просто нужно возможность в бп поставить галочку, запустить поверх текущего :))) Просто чтобы запустился сверху если его запускают при открытом другом бп

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

Уважаемый Александр!
Вы написали очень много и все не по теме. Прочитайте, пожалуйста, суть вопроса и потом, если вы его, наконец, поймете, дайте реальный совет, а не история про космические корабли, которые бороздят...

Простейший кейс: У вас в бп 2 задачи, всего 2 задачи. Выполнятся бп начал при изменении статуса продажи, соответственно перед Вами открылась карточка задачи. В задаче написано: "Александр, дорогой, пожалуйста, создай счет к заказу, который связан с продажей". В задаче, естественно, есть связь с заказом.
Внимание, Александр, вопрос: как так переделать и оптимизировать наш с вами бп из двух задач, чтобы мы могли перейти сразу из этой задачи в заказ и нажать кнопку "Создать счет", чтобы у нас открылась картчочка счета и перенеслись туда продукты ? Вы там про автогенерируемые и преднастроенные страницы говорили, как там они перед нами появятся, если можно скриншотик.

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

Добрый день, Д. В таком случае попробуйте прямо в этом БП сделать не 2 блока, а 6, при этом вторые 2 будут связаны с заказом, а третьи 2 — со счётом. Если пользователь будет идти по процессу, ему не нужно будет ни вручную создавать счёт, ни нажимать дополнительные кнопки в карточках, а карточка нового счёта  с уже заполненными полями связи с продажей и заказом автоматически появится при сохранении заказа в соответствии с логикой процесса. Дополнительную информацию пользователю, что от него хочет в этот момент система, можно показывать как раз в автогенерируемых страницах.

Коллеги, если есть возможность создать такой признак (стартовать бп поверх запущенного), это будет супер.
Спасибо.

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

Войдите или зарегистрируйтесь, чтобы комментировать