Вопрос

Всем доброго времени суток. Версия 7.12.

Есть ли возможность как-то отключить возможность выбора процессов по кнопке "Другой процесс", или хотя бы ограничить доступ к процессам, которые возможно запустить через панель быстрого запуска?

Или только через переопределение модуля LeftPanelTopMenuModule и соответствующие правки в loadMenu?

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

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

Добрый день, Денис!

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

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

Добрый день! Подскажите, пожалуйста, а имеется ли возможность с помощью командой строки искать по другим разделам, а не по разделу «Контакты»/«Контрагенты»? Как в этот выпадающий список добавить новый раздел?

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

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

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

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

В базовой версии продукта доступен функционал глобального поиска по всей системе. 

Более детально Вы можете ознакомиться с статье Академии: https://academy.terrasoft.ru/documents/studio/7-12/globalnyy-poisk

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

Если же сайт находится на Ваших серверах, в статье есть инструкция по настройке.

День добрый! Сайт развернут на серверах и глобальный поиск уже работает. Вопрос в том как поднастроить его таким образом чтобы добавить поиск еще по одному разделу: Сейчас поиск идет по Контактам и Контрагентам. Мне необходимо чтобы появилась еще строка "Найти Вакансию Тест"

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

Александр, выдача выдана просто списком с фильтром в выбранном разделе. 

Значит, глобальный не включен.

А без глобального поиска такое возможно реализовать? Просто как таковой глобальный поиск не нужен. Нужен быстрый доступ к поиску по разделу.

Как настраивать командную строку, описано здесь.

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

Всем доброго времени суток. Версия 7.12.

Есть бизнес-процесс, запускающийся вручную. Необходимо в процессе отловить пользователя, запустившего процесс. Подходит ли для этого переменная "Контакт текущего пользователя"/"Текущий пользователь"?

Второй случай. Бизнес-процесс запускается по сигналу от объекта (изменение какой-либо колонки). Можно ли в процессе отловить пользователя, изменившего колонку в объекте, т.е. запустившего процесс?

В более общем смысле вопрос - что есть "Контакт текущего пользователя" в бизнес-процессах? Если у нас показывается "Контакту текущего пользователя" страница редактирования какого-либо объекта, и одновременно в системе сидит несколько пользователей - она будет показана всем?

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

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

1) Да

2) Тут надо тестить, но я думаю нет (если, конечно, при запуске события не прокидывается UserConnection пользователя)

В общих чертах: есть UserConnection. Подключение пользователя, которое инициируется в момент вашего логина в СРМ. Соответственно "Контакт текущего пользователя" — контакт из UserConnection.

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

А все сервисы/бп по расписанию инициируются под userconnection от Supervisor-а.

2) Если в объекте в записи менялась колонка и по изменению запустился процесс, то сразу после запуска в поле ModifiedById этой записи и будет тот, кто поменял.

Варфоломеев Данила пишет:
А все сервисы/бп по расписанию инициируются под userconnection от Supervisor-а

а как определяется пользователь Supervisor, если он в системе не активный? 

Владимир Соколов пишет:
если он в системе не активный?

 AppConnection.SystemUserConnection всегда можно вытащить

Да и да. Пользователь, изменивший объект является инициатором триггерного процесса

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

Всем доброго времени суток.

Вопрос, наверно, простой - где определяется функция recalculateServiceTerms, в какой схеме?

Версия 7.12.

Нашёл несколько мест, где вызывается, нужно найти определение.

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

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

Если есть доступ в базу, поискать можно запросом:

SELECT (SELECT [Name] FROM [SysSchema] WHERE [Id] = [SysSchemaId])
FROM [SysSchemaContent]
WHERE CAST([Content] AS VARCHAR(MAX)) LIKE '%recalculateServiceTerms%'

И среди трёх результатов будет искомая схема CaseServiceUtility:

/**
 * Recalculates scheduled dates by service item.
 * @protected
 */
recalculateServiceTerms: function() {
	var config = this.getIsFeatureEnabled("ServiceTerms")
			? this.getCaseTermCalculatorServiceConfig()
			: this.getCallTermCalculationServiceConfig();
	if (config) {
		if (this.getIsFeatureEnabled("ServiceTerms")){
			this.callService(config, this.onRecalculateCaseTerms, this);
		} else {
			this.callService(config, this.onRecalculateServiceTerms, this);
		}
	} else if (this.get("ResponseDate")) {
		this.set("ResponseDate", null);
		this.set("SolutionDate", null);
	}
},

 

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

Коллеги, доброго дня!

Есть такой базовый элемент бизнес-процессов "Создать задачу". В дизайнере процессов можно от него нарисовать условные потоки, которые аналитик заполняет возможными результатами из справочника "Результаты Активности".

Каким образом можно настроить аналогичную автоматизацию для пользовательского элемента бизнес-процессов? Либо где посмотреть, как это уже реализовано для элемента "Создать задачу"?

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

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

3 комментария

Я не совсем понимаю, что требуется, если честно, но попытаюсь помочь :)

Возможно этот скрин поможет. Небольшой БП (чисто для примера не перенасыщал его дополнительными проверками и т.д.). Первая задача звучит так "Выяснить тип потребности в продаже". Менеджер вносит выбирает нужное значение в продаже, жмакает "Выполнена" и после этого мы читаем эту же продажу и в зависимости от того, что нужно клиенту, идем в нужную ветку и выполняем дальше задачи связанные с этим типом потребности. Если это не то, что Вам нужно, то объясните еще раз Ваш кейс :)

Добрый день!

Пример реализации данной логики в элементе "Выполнить задачу" Вы можете посмотреть открыв исходный код элемента "ActivityUserTask".

А можно чуть поподробнее, какой именно метод отвечает за указанный функционал?

Анна Журавель пишет:

Добрый день!

Пример реализации данной логики в элементе "Выполнить задачу" Вы можете посмотреть открыв исходный код элемента "ActivityUserTask".

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

Добрый час суток!

Немного не могу понять как построить запрос на UPDATE в мобильном приложении.

Например я хочу сделать такой запрос SQL

UPDATE TEST SET IsChecked = 1 WHERE Question = '' and Answer = ''

Я делаю так:
        var filters = Ext.create("Terrasoft.Filter", {
                type: Terrasoft.FilterTypes.Group,
                logicalOperation: Terrasoft.FilterLogicalOperations.And
            });
        filters.addFilter(Ext.create("Terrasoft.Filter", {
                property: "Question ",
                value: multiAnswerId // тут Id Question (для фильтра как выше)
        }));
        filters.addFilter(Ext.create("Terrasoft.Filter", {
                property: "Answer ",
                value: answerVariantId // тут Id Answer(для фильтра как выше)
        }));
        var sql = Terrasoft.Sql.UpdateBuilder.build({
                model: "Test", //Таблица в которую хочу сделать запрос
                queryConfig: queryConfig, //что это ?
                record: record, // что это?
                filter: filters,// это у меня есть
                includeOnlyModifiedColumns: true // что это?
        });
        sqls.push(sql);
        

Подскажите пожалуйста,как мне в мой обьект который я бросаю (var sql = ...) добавить по сути SET IsChecked =1 ? Ведь фильтры я уже сделал,а как сформировать немного не пойму.. может мне даже QueryConfig и includeOnlyModifiedColumns вообще ну нужны ? и достаточно как то константами сделать ? Спасибо заранее!

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

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

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

Вот пример фильтрации и перебора:

// Создание экземпляра хранилища для данных модели Contact.
var store = Ext.create('Terrasoft.store.BaseStore', {
    model: 'Contact'
});
 
// Создание конфигурационного объекта с дополнительными параметрами запроса на выборку данных.
var queryConfig = Ext.create('Terrasoft.QueryConfig', {
    // Определение колонок, которые будут возвращены в запросе.
    columns: ['Name', 'Id', 'Account'],
    // Имя модели, к которой выполняется запрос.
    modelName: 'Contact'
});
 
// Загрузка данных в хранилище. Будет возвращена первая страница данных.
store.loadPage(1, {
    queryConfig: queryConfig,
    // Дополнительно указывается фильтрация возвращаемых данных по колонке Name.
    filters: Ext.create('Terrasoft.Filter', {
        // Имя колонки, по которой выполняется фильтрация.
        property: 'Name',
        // Значение для фильтрации.
        value: 'Test Name'
    }),
    // Функция обработки результатов выполнения запроса.
    callback: function(records, operation, success) {
        // Получение первой записи возвращенного набора.
        var loadedRecord = records[0];
        if (loadedRecord) {
            // Получение значения поля Account.
            var contactAccount = loadedRecord.get('Account');                                                                                                    
            if (contactAccount) {                                                                                                                   
                // Выполнение действий с полученным значением.
            }
        }
    },
    scope: this
});

Вот пример изменения и сохранения записи (но новой, а не существующей):

var record = Ext.create('Contact');
record.phantom = true;
//свойство модели phantom указывает на то, новая ли это запись или существующая
record.set('Name', 'New Contact');
 
record.save({
    success: function() {
        ...
    },
    failure: function(exception) {
        Terrasoft.MessageBox.showException(exception);
    },
    queryConfig: Ext.create('Terrasoft.QueryConfig', {
        modelName: record.self.modelName,
        columns: ['Name']
    }
}, this);

 

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

var store = Ext.create('Terrasoft.store.BaseStore', {
            model: 'SuInterviewAnswerChoice'
        });

        var queryConfig = Ext.create('Terrasoft.QueryConfig', {
            columns: ['SuInterviewQuestion', 'SuAnswer', 'SuIsChecked'],
            modelName: 'SuInterviewAnswerChoice'
        });
        
        store.loadPage(1, {
            queryConfig: queryConfig,
            filters: Ext.create('Terrasoft.Filter', {
                property: 'SuInterviewQuestion',
                value: multiAnswerId
            }),
            callback: function(records, operation, success) {
                for(var i =0; i<records.length;i++){
                    if(records[i].data.SuAnswer === answerVariantId){
                        var isChecked = records[i].get('SuIsChecked');
                        if(!isChecked){
                            records[i].set('SuIsChecked',true);
                            records[i].save({
                                success: function() {
                                    console.log('Successfully');
                                },
                                failure: function(exception) {
                                    Terrasoft.MessageBox.showException(exception);
                                },
                                queryConfig: Ext.create('Terrasoft.QueryConfig', {
                                    modelName: records[i].self.modelName,
                                    columns: ['SuIsChecked']
                                })
                            }, this);
                            return;
                        }
                    }
                    
                }
            },
            scope: this
        });

 

 

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

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

да,меняет. Поле ModifiedOn меняется. Подскажите пожалуйста еще,как правильно написать Insert,спасибо!

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

Зверев Александр пишет:

Вот пример изменения и сохранения записи (но новой, а не существующей):


 
var record = Ext.create('Contact');
record.phantom = true;
//свойство модели phantom указывает на то, новая ли это запись или существующая
record.set('Name', 'New Contact');
 
record.save({
    success: function() {
        ...
    },
    failure: function(exception) {
        Terrasoft.MessageBox.showException(exception);
    },
    queryConfig: Ext.create('Terrasoft.QueryConfig', {
        modelName: record.self.modelName,
        columns: ['Name']
    }
}, this);

или я так понимаю вот это можно использовать вместо InsertBuilder?

 

Да, лучше вместо InsertBuilder использовать редактирование и сохранение записи.

Зверев Александр,Спасибо

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

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

Зверев Александр пишет:

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

Вот пример фильтрации и перебора:


 
// Создание экземпляра хранилища для данных модели Contact.
var store = Ext.create('Terrasoft.store.BaseStore', {
    model: 'Contact'
});
 
// Создание конфигурационного объекта с дополнительными параметрами запроса на выборку данных.
var queryConfig = Ext.create('Terrasoft.QueryConfig', {
    // Определение колонок, которые будут возвращены в запросе.
    columns: ['Name', 'Id', 'Account'],
    // Имя модели, к которой выполняется запрос.
    modelName: 'Contact'
});
 
// Загрузка данных в хранилище. Будет возвращена первая страница данных.
store.loadPage(1, {
    queryConfig: queryConfig,
    // Дополнительно указывается фильтрация возвращаемых данных по колонке Name.
    filters: Ext.create('Terrasoft.Filter', {
        // Имя колонки, по которой выполняется фильтрация.
        property: 'Name',
        // Значение для фильтрации.
        value: 'Test Name'
    }),
    // Функция обработки результатов выполнения запроса.
    callback: function(records, operation, success) {
        // Получение первой записи возвращенного набора.
        var loadedRecord = records[0];
        if (loadedRecord) {
            // Получение значения поля Account.
            var contactAccount = loadedRecord.get('Account');                                                                                                    
            if (contactAccount) {                                                                                                                   
                // Выполнение действий с полученным значением.
            }
        }
    },
    scope: this
});

 

Работайте асинхронно, через callback.

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

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

Основная логика bpm'online реализуется в веб-версии, мобильная имеет вспомогательное применение, её SDK не настолько подробен и не включает всех возможных сценариев. Если у Вас есть необходимость в какой-то логике, которую не реализовать иначе, можете завести идею, описать там подробно своё пожелание и, возможно, в новых версиях такое реализуют.

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

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

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

Ну и соотвественно обратно снимать, если это условие перестает соблюдаться.

Каким способом лучше это сделать?

Спасибо!!)

 

 

 

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

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

Бп. А в странице к описанию детали влепить subscriber и делать loadEntity (грубо говоря — аналогично стандартной логике в заказе)

Бп. А в странице к описанию детали влепить subscriber и делать loadEntity (грубо говоря — аналогично стандартной логике в заказе)

Можно и триггером в базе вместо БП. Особенно, если на деталь льют записи извне в обход движка EntitySchemaQuery.

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

Трефилов Павел Сергеевич,

ContactAnniversary: {
	schemaName: "ContactAnniversaryDetailV2",
	filter: {
		masterColumn: "Id",
		detailColumn: "Contact"
	},
	subscriber: {
		"methodName": "sendSaveCardModuleResponse"
	}
}

Вот, допустим, из базовой страницы контакта. Метод sendSaveCardModuleResponse располагается в BasePageV2. Встаньте туда дебаггером через консоль и попробуйте поудалять/подобавлять записей в деталь "знаменательные события". При каждом изменении чего-нибудь в детали - тут же отрабатывает метод. В идеале в нём же делать this.reloadEntity (чтобы обновились поля карточки, которые были перерасчитаны по бп)

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

Данила, спасибо огромное! Сделали. 

Только тут асинхронность проявилась. Сабскрайбер отрабатывает и обновляет страницу быстрее чем отрабатывает БП. Как послать сигнал из БП чтобы страница обновилась после завершения БП. Ну кроме, как таймаут ставить). Спасибо!!!

Елена К,

Ничего адекватного, кроме переделки всех пересчётов под клиентский esq, посоветовать в таком случае не могу (ну за исключением костыля - отправки сообщения по websocket в конце бп).

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

Да, так и сделали. Спасибо вам!!)

 

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

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

В элементе процесса "Открыть страницу редактирования" не стоит галочка "Выполнять в фоновом режиме". Согласно статье на академии в таком случае будет открываться страница этого шага, прерывая любые действия пользователя. Но это элемент выполниться только в том случае если перейти на него на вкладке [Задачи по бизнес-процессам] коммуникационной панели.

Как правильно настроить элемент, чтобы он открывался сразу при переходе на данный шаг процесса?

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

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

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

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

Александр, в стартовом сигнале галочка тоже отсутствует, но все равно возникает такая ситуация.

Значит, процесс с какого-то момента переходит в фон. Например, из-за таймера. Или же просто в карточке той записи ответственный не текущий пользователь.

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

Спасибо большое! Сейчас посмотрю.

Александр, Проверил все еще раз. Ответственный - текущий пользователь. Таймеров никаких нет, что может еще переводить процесс в фон?

 

Ещё он будет в фоне, если запускать из дизайнера процессов, поскольку в этот момент не активна вкладка, на которой должна появится страница.

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

Спасибо!

Так у Вас процесс или кейс?

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

 

Если не открывается только эта страница, то что-то не то в самой странице. Если любая — то в процессе. Попробуйте поэкспериментировать с другими страницами, со специально созданными маленькими процессами из 1 элемента, открывающего эту страницу.

odins41,

Для того, чтобы интерактивный элемент (страница редактирования/вопрос пользователю/ т.д.) открылась автоматически должны выполнится следующие условия:
1. Процесс не выполняется в фоне, т.е:
- в расширенных свойствах стартового элемента не должна стоять галочка "выполнять в фоне"
- по ходе процесса не должно быть таймеров 
2. Пользователь, которому должна открыться страница, должен быть инициатором процесса
3. Пользователь должен быть ответственным за элемент
4. Пользователь находится в контексте текущего процесса., т.е. если пользователь работая по одному процессу параллельно запускает второй процесс – интерактивные элементы по второму БП автоматически не откроют страницу

Если все описанные више условия выполняются, а страница все равно не открывается напишите, пожалуйста, на support@bpmonline.com

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

Добрый день, делаю звонок с кнопки:

 this.sandbox.publish("CallCustomer", {
                    number: mobNumber, 
                    customerId: userId, 
                    entitySchemaName: "SxCandidate",
                    callRelationFields: undefined
                });

Есть ли возможность как то узнать Id этого звонка? Той записи которая добавляется в таблицу "Call". Спасибо!

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

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

Смотря какая телефония. У вебитела, например есть чудеснейшая функция UpdateDbCall в провайдере, которая делает запись в бд через insert (пока-пока событийные бп), и возвращает Id вставленной записи в onUpdateDbCall

Телефония Asterisk

mcNosferatum,

Есть у меня подозрение, что для asterisk-а интеграция встроена в dll в виде класса и звонок там вставляется через те же insert-ы. Тогда смотреть стоит в сторону обработчиков событий звонка в ctipanel. Мб там где-нибудь guid звонка приходит...

А что в Network'е? Какие запросы/ответы при звонке? Просто в стандартном Webitel запрос на звонок к серверу как раз возвращает в ответе Id звонка, может у Asterisk такая же логика.

На самый крайний случай можно просто сделать esq запрос в БД с таким количеством параметров, которые однозначно идентифицируют звонок.

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

Всем доброго времени суток. Версия 7.11.

Есть хорошая и простая функция для открытия мини-карточки:

this.openMiniPage({
	recordId: Terrasoft.GUID_EMPTY,
	operation: Terrasoft.ConfigurationEnums.CardOperation.ADD,
	entitySchemaName: "Case",
	valuePairs: defaultValues,
	isFixed: true,
	showDelay: 0,
	miniPageSchemaName: "UsrCaseMiniPage",
});

Всё отлично - и указание на операцию, и на схему объекта и страницы. Особо удобно здесь свойство valuePairs, позволяющее передать значения для презаполненных колонок.

Существуют ли подобные функции для открытия полноценной карточки добавления?

Нашёл openPage в PageUtilities, но не нашёл, чтобы там был аналог valuePairs.

PushHistoryState не подходит - с его помощью можно открыть существующую страницу, а интересует именно страница добавления.

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

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

Смотрите, как сделано в базовой схеме раздела BaseSectionV2. Там в обработчике кнопки добавления если есть миникарточка, вызывается Ваша функция openAddMiniPage, а если нет — openCardInChain:

/**
 * Opens new record page.
 * @protected
 */
addRecord: function(typeColumnValue) {
	if (!typeColumnValue) {
		if (this.checkEditPagesCount()) {
			return false;
		}
		var tag = this.get("AddRecordButtonTag");
		typeColumnValue = tag || Terrasoft.GUID_EMPTY;
	}
	var schemaName = this.getEditPageSchemaName(typeColumnValue);
	if (!schemaName) {
		return;
	}
	if (this.hasAddMiniPage(typeColumnValue)) {
		this.openAddMiniPage({
			entitySchemaName: this.entitySchemaName,
			valuePairs: this.getAddMiniPageDefaultValues(typeColumnValue)
		});
	} else {
		this.openCardInChain({
			schemaName: schemaName,
			operation: ConfigurationEnums.CardStateV2.ADD,
			moduleId: this.getChainCardModuleSandboxId(typeColumnValue),
			instanceConfig: {
useSeparatedPageHeader: this.get("UseSeparatedPageHeader")
			}
		});
	}
},

 

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