Подскажите, не получается для showConfirmationDialog сделать LocalizableString.

Кнопка попросту не отображается, до тех пор пока в caption не введу конкретную строку.

var ButtonDoItCfg= {
"className": "Terrasoft.Button",
"returnCode": "ButtonDoIt",
"style": "green",
"caption": { "bindTo": "Resources.Strings.ButtonDoItCaption" }
};
var cfg = {
style: Terrasoft.MessageBoxStyles.BLUE
};
this.showConfirmationDialog( cs1 + " " + cs2,
function getSelectedButton(returnCode) {
if (returnCode === Terrasoft.MessageBoxButtons.YES.returnCode) {
var args = {
sysProcessName: "ButtonDoItProcessCode",
parameters: {
BPcs1: csID1,
BPcs2: csID2
}
};
ProcessModuleUtilities.executeProcess(args);
}
}, ["yes", "no", ButtonDoItCfg], cfg);

 

Нравится

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

1) Возможно вы зыбыли в самой схеме пробросить объект Resources для зависимости

 

define("LeadPageV2", ["LeadPageV2Resources"], function(resources) {
...

т.е. в зависимостях необходимо добавить {Имя схемы}Resources

и на "вход" результирующей функции соответствующий аргумент, в итоге получите а контексте карточки объект вот такой

в Вашем коде соответственно используйте не текстовую мнемонику 

"Resources.Strings.ButtonDoItCaption"

а прямо передавайте необходимое свойство объекта.

PS: я сомневаюсь что в жизненном цикле карточки у Вас происходит изменение локализуемых строк...

Показать все комментарии

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

Нравится

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

имеется в виду бизнес-процесс ?

Севостьянов Илья Сергеевич,

Да.

я не уверен, что такая возможность имеется, именно в виде "изменить бизнес-правило", но можно создать бизнес-правила выполнение которых зависит от значения атрибута модели, и например "скрытое поле" в целевом объекте, в бизнес-процессе устанавливать значение в это поле, а в целевой схеме предусмотреть логику (н/п в onEntityInitialized) которая опираясь на значение вышеуказанного поля будет устанавливать значение в атрибут модели.

Итоговый результат, ИМХО - это тот кейс, который вы хотите реализовать, насколько я понял.

Показать все комментарии

пользователи спрашивают как копировать строки деталей.

из идей как это сделать.

Привязать действие на кнопку три точки в детали

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

 

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

Нравится

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

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

Сделайте на детали редактируемый реестр - там уже есть кнопка, которая позволяет скопировать запись. Также в базовой версии на "трех точках" (на действиях детали) уже есть кнопка копирования (см. деталь "Адреса" на странице раздела "Контакты").

Добрый день, Марат! 

Если еще актуально или необходимо для другого кейса - у BasePageV2 есть методы loadDetail и reloadDetail. Также отмечу, что "обновить" деталь можно изменив направление или колонку сортировки.

reloadDetail - идеальный кандидат.

Показать все комментарии

Добрый день!





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

Например, в продаже есть деталь контакты, при нажати на плюс страница добавления нового контакта открывается в новой вкладке. 

Нравится

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

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

При нажатии на "Добавить" возможны два варианта:

  • Открывается миникарточка контакта
  • Открывается страница редактирования новой записи контакта (в том же окне)

Предполагаю, что имеется ввиду именно миникарточка. Для базовых разделов системы уже предусмотрена миникарточка. Ее появление регласметируется системной настройкой "Использовать миникарточку добавления [#записи#]", где [#запись#] - это название сущности, например, контакта, контрагента, активности.

Если нужна миникарточка, а ее в системе нет, тогда ее нужно создать. Инструкция по созданию:

https://academy.terrasoft.ru/documents/technic-sdk/7-10/sozdanie-mini-k…

Здравствуйте, открытие карточки добавления записи детали по "+" невозможно в новой вкладке т.к. требует "истории" и "контекста" что невозможно передать на текущий момент через url. А открытие в новой вкладке может быть реализовано только лишь через url.

Показать все комментарии

Стоит следующая задача: если в карточке контакта изменилось текущее значение поля [Статус] на 'Reject', задать пользователю вопрос вида: "Вы, действительно, хотите установить 'Reject' статус", если пользователь отвечает да, тогда должен запускаться БП, который изменит статусы других, связанных объектов, если нет, тогда статус должен возвращаться в предыдущее состояние.

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

Для поля [Статус] создано dependencies, в котором реализован вызов следующего метода:

               var status = this.get("BTContactStatus");

                if (this.Ext.isEmpty(status)) {

                    return;

                }

                if (status.value === "f7ade63f-213d-4daa-a73d-75684c4bd689") {

                    var message = "Do you want set 'Reject' status?";

                    this.showConfirmationDialog(this.Ext.String.format(message, 1), function (result5) {

                        if (result5 === Terrasoft.MessageBoxButtons.NO.returnCode) {

                             var entity = Ext.create("Terrasoft.EntitySchemaQuery", {

                                rootSchemaName: "Contact"

                            });

                            entity.addColumn("BTContactStatus");

                            entity.filters.addItem(entity.createColumnFilterWithParameter(

                            this.Terrasoft.ComparisonType.EQUAL, "Id", this.get("Id")));

                            entity.getEntityCollection(function(result) {

                                if (result.success) {

                                    if(result.collection.getCount() < 1) {

                                        this.set("BTContactStatus", null);

                                        return;

                                    }

                                    this.set("BTContactStatus", result.collection.getByIndex(0).get("BTContactStatus"));

                                }

                            }, this);

                        }

                    }, ["yes", "no"]);

                }

В методе описан сценарий, когда пользователь на вопрос отвечает 'Нет', а если пользователь на вопрос отвечает 'Да', в методе ничего не происходит, но в системе реализован процесс, который запускается по сигналу изменения статуса у контакта на 'Reject'.

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

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

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

И насколько целесообразно в данной задаче использовать валидацию для поля или есть другие способы решения данной задачи?

 

 

 

Нравится

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

Для контроля изменения в поле - необходимо установить на него dependencies (свойство конфигурационного объекта атрибута)

https://academy.terrasoft.ru/documents/technic-sdk/7-10/atributy-svoystvo-attributes

н/п установим метод обработчик для поля "Contact"

attributes:{
...
"Contact": {
	dependencies: [
		{
			columns: ["Contact"],
			methodName: "ContactChangeHandler"
		}
	]
}
...
},

вашу логику вынести в метод обработчик

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

Terrasoft.utils.showMessage({
	caption: "Ваше сообщение пользователю",
	//набор используемых кнопок из списка стандартных для диалоговых окон
	buttons: ["yes", "no"],
	//метод-обработчик выполненных пользователем действий
	handler: function(code) {
		//если пользователь нажал "Да"
		if (code === "yes") {
			//ToDo
		//если пользователь нажал "Нет"
		//проверять необходимо явно, т.к. окно можно и просто закрыть
		} else if (code === "no") {
			//ToDo
		//логика "по умолчанию"
		} else {
			//ToDo
		}
	},
	defaultButton: 0,
	//контекст в котором будет вызвана функция обработчик handler
	scope: this
});



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

н/п создав специальный атрибут

attributes:{
...
"rollbackByContactChangeFlag": {
	"type": Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
	"dataValueType": Terrasoft.DataValueType.BOOLEAN,
	"value": false
}
...
},

в начале же вашего метода-обработчика изменения ориентируйтесь на его значение. 

Показать все комментарии

Добрый день! Возник вопрос по воронкам - можно ли в bpm создать воронку, которая бы показывала продвижение сделки от лида (переход по всем стадиям), затем по стадиям продажи, по состояниям заказа и вплоть до оплаченного счета (чтобы все данные отображались в одной воронке)?

Нравится

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

Думаю, что с помощью стандартных средств реализовать такую задачу не получится. Как минимум, для её реализации нужно сделать специальное представление, которое соберет информацию по всем сущностям. Вьюху можно реализовать с помощью конструкции union в sql.

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

Показать все комментарии

Здравствуйте. Как можно загрузить файл через API (odata) и прикрепить его к определенному контакту/лиду/заданию/звонку и тп? Пробовал через модели odata, но выдавало ошибку, что такая модель еще не доступна. Скорее всего, я что-то не так делал. Может кто-то сталкивался с таким вопросом. Буду рад любой помощи. Спасибо.

Нравится

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

как по мне очень похоже на вот это: https://community.terrasoft.ru/questions/realizacia-peredaci-pdf-dokume…;

Там конечно про pdf, но описанные действия вроде подходят для всех типов файлов. 

Спасибо. Сейчас делаю так:

1. POST запрос с привязкой к контакту и задаю название файла.

2. PUT запрос передаю файл.

Но на 2 этапе возникает проблема. Когда я передаю файл через POSTMAN и позже его скачиваю из CRM. Файл не открывается должным образом. Открыв файл через notepad++ и забрав такие заголовки

----------------------------606529554623297003963904
Content-Disposition: form-data; name=""; filename="bcr_scren.png"
Content-Type: image/png

картинка (в данном случае) открывается нормально.

При этом я создал PHP скрипт у себя на сервере для загрузки файлов и передаю точно такие-же параметры и заголовки как и в CRM. Файл загружается без проблем.

Скрин из POSTMANa:

Заголовок запроса такой: Content-Type: multipart/form-data.

Вы используете обычный EntityDataService. Но, судя по ссылке, есть отдельный FileApiService именно для работы с файлами. Примеры работы с ним можно увидеть в самой системе на детали файлов, а уходящие из браузера запросы на сервер посмотреть в Fiddler.

См. примеры тут.

Посмотрите, как работает с файлами через этот сервис интерфейс системы. Готовых примеров решения такой задачи на PHP нет, поскольку bpm'online использует JS на клиенте и С#  на сервере. Следовательно, найти примеры на этих языках шансов намного больше.

Запустил Fiddler, добавил файл на деталь, POST-запросы к сервисам записались нормально. Сначала собственно добавление:

/0/rest/FileApiService/Upload?fileapi15301911041375&totalFileLength=13036&fileId=935b6ecb-3509-4c8a-bc7e-03ab0661da24&mimeType=&columnName=Data&fileName=myfilename.rar&parentColumnName=Contact&parentColumnValue=c4ed336c-3e9b-40fe-8b82-5632476472b4&entitySchemaName=ContactFile

В качестве содержимого запроса — сам файл.

Потом запрос на выборку :

/0/DataService/json/SyncReply/SelectQuery

С содержимым:

{"rootSchemaName":"ContactFile","operationType":0,"filters":{"items":{"primaryColumnFilter":{"filterType":1,"comparisonType":3,"isEnabled":true,"trimDateTimeParameterToDate":false,"leftExpression":{"expressionType":1,"functionType":1,"macrosType":34},"rightExpression":{"expressionType":2,"parameter":{"dataValueType":0,"value":"935b6ecb-3509-4c8a-bc7e-03ab0661da24"}}}},"logicalOperation":0,"isEnabled":true,"filterType":6},"columns":{"items":{"Id":{"caption":"","orderDirection":0,"orderPosition":-1,"isVisible":true,"expression":{"expressionType":0,"columnPath":"Id"}},"Name":{"caption":"","orderDirection":0,"orderPosition":-1,"isVisible":true,"expression":{"expressionType":0,"columnPath":"Name"}},"Type":{"caption":"","orderDirection":0,"orderPosition":-1,"isVisible":true,"expression":{"expressionType":0,"columnPath":"Type"}},"Version":{"caption":"","orderDirection":0,"orderPosition":-1,"isVisible":true,"expression":{"expressionType":0,"columnPath":"Version"}},"CreatedBy":{"caption":"","orderDirection":0,"orderPosition":-1,"isVisible":true,"expression":{"expressionType":0,"columnPath":"CreatedBy"}},"Notes":{"caption":"","orderDirection":0,"orderPosition":-1,"isVisible":true,"expression":{"expressionType":0,"columnPath":"Notes"}},"EntryPointsCount":{"caption":"","orderDirection":0,"orderPosition":-1,"isVisible":true,"expression":{"expressionType":3,"aggregationType":1,"columnPath":"[EntryPoint:EntityId].Id","subFilters":{"items":{"c11b1561-6443-42de-8768-f6db6d774678":{"filterType":1,"comparisonType":3,"isEnabled":true,"trimDateTimeParameterToDate":false,"leftExpression":{"expressionType":0,"columnPath":"IsActive"},"rightExpression":{"expressionType":2,"parameter":{"dataValueType":1,"value":true}}}},"logicalOperation":0,"isEnabled":true,"filterType":6}}}}},"isDistinct":false,"rowCount":-1,"rowsOffset":-1,"isPageable":false,"allColumns":false,"useLocalization":true,"useRecordDeactivation":false,"serverESQCacheParameters":{"cacheLevel":0,"cacheGroup":"","cacheItemName":""},"isHierarchical":false}

 

 

 

 

 

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

Так и делаю, шлю POST на URL

https://bookimed.bpmonline.com/0/rest/FileApiService/Upload?fileapi15301911041375&totalFileLength=".filesize($localfile)."&fileId=" . $fileId . "&mimeType=&columnName=Data&fileName=test.png&parentColumnName=Order&parentColumnValue=f106146d-817a-4359-a7a8-a2386c14c7bb&entitySchemaName=OrderFile

А в ответ получаю The server encountered an error processing the request. The exception message is 'Невозможно определить размер файла'

Хотя я передаю totalFileLength в строке запроса - эту ошибку тоже вспоминали тут https://community.terrasoft.ru/questions/fileapiservice-zagruzka-dokume… и но не объяснили как побороть

Видимо, размер реально оказывается не тот или не в том формате. Сравните в Fiddler Ваш и автоматический запросы.

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

 Разобрался! Нужно в хэдере еще указывать

'Content-Range: bytes 0-'.(filesize(realpath($localfile))-1).'/'.filesize(realpath($localfile)),

АПИ уже работает и отвечает ОК

Спасибо за важное уточнение.

Показать все комментарии

Задача модифицировать настройки(расписание) автоматического поиска дублей контактов и контрагентов.

Данный функционал заявлен в пакете Dedupliction, но по факту не работает для контрагентов, всегда выбирается настройка для контактов.

Параметр entitySchemaName в модуле SearchDuplicatesSettingsPageViewModel. При вызове метода generate не заполняется.

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

Создал UsrSearchDuplicatesSettingsSection, наследованный от Базовая схема раздела ( NUI ). В нём в define собственно указал только параметр

entitySchemaName: "DuplicatesSearchParameter".

А для вызова этой страницы в замещённом DuplicatesRuleSectionV2 сделал вызов

openScheduleSettingPage: function() {
  this.sandbox.publish("PushHistoryState", {
    hash: "SectionModuleV2/UsrSearchDuplicatesSettingsSection"
  });
}

В итоге получаю ошибку про name primaryDisplayColumn. Оказывается он не заполняется в getSectionDefaultGridSettings (там цепочка вызова  require) модуля ProfileUtilities.js.

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

Нравится

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

Добрый день, Павел! 

Дело в том, что в это объекте действительно не заполнено данное свойство, он и не создавался для использования в кастомных схемах. Вы указали тег 7.10, но проблема, которая описана в вопросе, была в версии 7.9.1, и исправлена в 7.9.2 - у AccountPageV2  из пакета Deduplication была entitySchemaName : Contact. Подскажите, это тег неверный, или же действительно воспроизводится в 7.10? Если второй вариант, обязательно напишите письмо в официальную поддержку.

Здравствуйте, Владимир.



Спасибо за ответ.

Немного поясню ситуацию. Насколько я выяснил, функционал страницы настройки автоматического поиска дублей контактов и контрагентов реализован в 3-х файлах пакета NUI: SearchDuplicatesSettingsPage, SearchDuplicatesSettingsPageView, SearchDuplicatesSettingsPageViewModel.

Страница SearchDuplicatesSettingsPage вызывается методом openScheduleSettingPage в файле DuplicatesRuleSectionV2.

То есть страница вызывается не со страниц контакта, или контрагента.

Поэтому параметр entitySchemaName не заполняется, что собственно и продемонстрировано:

То есть, насколько я понял, остаётся замещать данные три модуля. Что конечно, будет затруднительно, чтобы поместить на страницу grid с возможностью добавления и удаления строк и придерживаться стилистического оформления.

Да, версия 7.10.2.

Павел, здравствуйте!

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



Если у Вас в 7.10.2 действительно возникают проблемы с тем что выбираются настройки для другого объекта, повторюсь, прошу написать письмо на support@terrasoft.ru с указанием Вашего сайта и данных для доступа.

Показать все комментарии

Добрый день!





Подскажите примеры реализации макросов.



https://academy.terrasoft.ru/documents/technic-sdk/7-10/dobavlenie-obra…

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

Задача следующая, необходимо отправлять e-mal уведомление  о назначении активности.

В теле письма нужно указывать заголовок активности.

Нравится

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

Светлана, пример решения Вашего кейса можно решить с помощью БП - https://academy.terrasoft.ru/documents/technic-bpms/7-10/kak-uvedomit-s…

Спасибо за помощь!

Показать все комментарии

Подскажите как добавить связь раздела "Согласующие" в список выбора?

Изображение удалено.

Нравится

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

Для того чтобы добавлять произвольные "Связи" в штатную механику, Вам необходимо добавить ее описание в таблицу EntityConnection

  • SysEntitySchemaUId (это реплика к значению колонки UId из таблицы SysSchema запись в которой описывает схему объекта для которого устанавливается связь
  • ColumUId (это реплика к одноименному полю в таблице SysEntitySchemaReference запись в которой отражает связь объекта с субъектом и его полем, фактически является описанием соотношения справочных полей в объектах)

изучите на примере уже существующих связей.



PS: в помощь Вам SQL скрипт который поможет Вам найти нужное значение по имени колонки и схемы от которой строится связь

-- Ищем колонку Лида (Lead) в схеме Активности (Activity)
SELECT SysEntitySchemaReference.*, Name FROM SysEntitySchemaReference SysEntitySchemaReference
INNER JOIN dbo.SysSchema SysSchema ON SysEntitySchemaReference.SysSchemaId = SysSchema.Id
WHERE ColumnName = 'Lead' AND Name = 'Activity'

Севостьянов Илья Сергеевич,

Все намного проще:

1. Добавить в объект Activity колонку, ссылающуюся на нужный справочник .

2. Найти UId колонки добавленной в первом пункте (в метаданных справочника).

3) Выполнить скрипт предоставленный раннее

     INSERT INTO EntityConnection (SysEntitySchemaUId, ColumnUId) VALUES ('C449D832-A4CC-4B01-B9D5-8A12C42A9F89', 'UId_колонки_из_п.2');

     Где UId колонки - UId колонки для связи из метаданных обьекта Activity.

4) Выполнить очистку кэша и перезайти в систему.

Последовательность правильная. В п.3 можно использовать более удобный скрипт для MSSQL:

 

DECLARE @columnName varchar(max) = 'UsrColumn';
INSERT INTO [EntityConnection] ([SysEntitySchemaUId], [ColumnUId])
  VALUES (
	(SELECT
	  [UId]
	FROM [SysSchema]
	WHERE [Name] = 'Activity'
	AND [ExtendParent] = 0), 
	(SELECT DISTINCT
	  [ColumnUId]
	FROM [SysEntitySchemaReference]
	WHERE [SysSchemaId] IN (SELECT
	  [Id]
	FROM [SysSchema]
	WHERE [Name] = 'Activity')
	AND [ColumnName] = @columnName));

 

Показать все комментарии