Здравствуйте. Как можно загрузить файл через 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)),

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

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

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

Собственно, нужно получить некие данные с внешнего API, и потом нарисовать их на странице раздела. Прошу подсказки, в какую сторону смотреть и двигаться. В Академии есть пример с добавлением строки-приветствия. Однако, совсем не понятен принцип работы кода с примера. Документация по Terrasoft Javascript API так же не понятна. Прошу подсказки, куда смотреть и в какую сторону двигаться.

Нравится

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

Если сервер API предоставляет специализированные заголовки CORS то в Вашем распоряжении вся мощь JavaScript в клиентской схеме, делайте запросы (н/п используя инструментарий используемой библиотеки Ext.JS AJAX), обрабатывайте ответы - устанавливайте атрибуты для заполнения полей и т.д.

Если сервер API не предоставляет специализированные заголовки CORS то в данном случае Вам придется писать код C# (Здесь я сильно не подскажу что да как, веб-сервис что-то там такое есть)
После чего можете например по websocket протоколу пробросить события с данными в клиентские карточки (как это сделать обсуждалось вот здесь)

"Севостьянов Илья Сергеевич" написал:Если сервер API не предоставляет специализированные заголовки CORS то в данном случае Вам придется писать код C#

Из js вызываете сервис. В сервисе обычные post/get запросы с помощь System.Web. Получаете ответ от сервера, делаете return, в js-коллбеке проходит ответ в json-строке. Сериализуете, обрабатываете далее как угодно

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

Пытаюсь получить связанную структуру по url

0/ServiceModel/EntityDataService.svc/UsrKinoAndSetyCollection(guid'57be85d8-913f-483e-a349-8bb40b212257')/UsrProductDetailCollectionByUsrKinoteatr

в ответ приходит

{
  "error": {
    "code": "4",
    "message": {
      "lang": "",
      "value": "Not Implemented"
    },
    "innererror": {
      "message": "Not Implemented",
      "type": "System.Data.Services.DataServiceException",
      "stacktrace": "   at System.Data.Services.WebUtil.GetRequestEnumerator(IEnumerable enumerable)\r\n   at System.Data.Services.DataService`1.SerializeResponseBody(RequestDescription description, IDataService dataService, IODataResponseMessage responseMessage)\r\n   at System.Data.Services.DataService`1.HandleRequest()",
      "internalexception": {
        "message": "Method 'SelectMany' not supported",
        "type": "System.NotSupportedException",
        "stacktrace": "   at Terrasoft.Core.Entities.EntityQueryProvider.VisitMethodCall(MethodCallExpression node)\r\n   at Terrasoft.Core.Entities.EntityQueryProvider.Build(Expression expression)\r\n   at Terrasoft.Core.Entities.EntityQueryProvider.LoadEntityCollection(Expression expression)\r\n   at Terrasoft.Core.Entities.EntityQueryProvider.ExecuteEnumerable(Type elementType, Expression expression)\r\n   at Terrasoft.Core.Entities.EntityQuery`1.GetEnumerator()\r\n   at System.Data.Services.WebUtil.GetRequestEnumerator(IEnumerable enumerable)"
      }
    }
  }
}

В чем ошибка?

Нравится

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

Здравствуйте, Сергей.

Уточните пожалуйста версию системы.

"Мария Ватулина" написал:

Здравствуйте, Сергей.

Уточните пожалуйста версию системы.


версия 7.10.0.1742

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

Есть сущность кинотеатры и сущность продукты. Кинотеатр может быть связан(пользоваться) с несколькими продуктами. Так же продукт может быть использоваться в нескольких кинотеатрах. Я пытаюсь получить продукты которыми пользуется определенный кинотеатр.

Добрый день, Сергей.

Приведем пример запроса по аналогии (на примере таблиц Активности, Контакты и Участники Активностей).

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

ActivityCollection?$select=Title,StartDate,DueDate&$filter=(ActivityParticipantCollectionByActivity/any(x:%20x/Participant/Id%20eq%20(guid%2724cf58c3-3926-4bff-9353-b8ef887f7b17%27)))
)

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

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

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

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

На википедии написано:
Bpm'online has been developed using Microsoft .Net architecture in combination with AJAX and HTML. Combined with RESTful APIs, it provides developers with a well-constructed SaaS architecture.

Есть ли где-нибудь задокументированный REST API? Всё, что я смог с большим трудом найти, это вот эта страница:
http://academy.terrasoft.ru/documents/docs/technic/SDK/7.6.0/RequestAuth...

Нравится

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

Здравствуйте!
Система поддерживает интеграцию через Odata.
Детальнее можно прочитать тут: http://academy.terrasoft.ru/documents/docs/technic/SDK/7.6.0/Integratio…
Это в той же ветке, что и ваша ссылка. Вот ссылка на корень ветки, посвященной интеграциям: http://academy.terrasoft.ru/documents/docs/technic/SDK/7.6.0/Integratio…

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

Не поверите :) Сейчас как раз в процессе перевода на новый движок. Планируем за 1,5-2 мес обновиться. Так что релиз 7.8 будет с новой Академией.

Кстати, если есть еще пожелания по Академии - тут их тоже можно писать.

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

Актальная документация доступна по ссылке https://academy.terrasoft.ru/documents/technic-sdk/7-12/integraciya-s-s…

Из этой документации абсолютно непонятно каким образом делать добавление заказа? какой использовать SchemaRoot? Какие поля передавать? Хотелось бы получить ответы на эти вопросы.

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

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

Показать все комментарии
Добрый день!Планируется ли в bpm'online развивать интеграцию с Facebook? Например, для bpm'online marketing - собирать Like&Comments с Facebook page и Facebook Ads? Для остальных продуктов - интеграция с Facebook messages?
0 комментариев
Показать все комментарии

Добрый день!
Подскажите пожалуйста, как в BPMOnline программно запустить БП и передать ему параметры?
Буду благодарен за пример.

Нравится

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

1)приведите пожалуйста пример
2) укажите продукт и версию продукта (5.4.0.195 - пример)

"Sergey Karpenko" написал:

1)приведите пожалуйста пример

2) укажите продукт и версию продукта (5.4.0.195 - пример)


1) Необходимо запустить БП из карточки лида (по факту квалификации). Использовать задачу "подпроцесс" не могу из-за проблем описанных в Как вызвать БП из процесса карточки (по событию). Хотел использовать программный запуск как обходной вариант.
2) BPMOnline CRM OnDemand Версия 5.4.0.195

Валерий, программно конечно можно запустить БП, но можно ведь обойтись и без кода, настроив БП на автоматический запуск по сигналу (добавлен новый контрагент + еще один сигнал добавлен новый контакт), вторым шагом в процессе установить проверку: если у контакта\контрагента записи на детали "Лиды" существуют (Account.LeadId != null, Contact.LeadId !+ null), значит он был создан в рамках квалификации, значит продолжаем выполнения БП, в противном случае - "конец".

Дмитрий, спасибо за ответ.
Да, действительно, такой вариант можно использовать, но мне кажется программный подход здесь будет более элегантным.
И если есть открытый API для вызова БП, то хотелось бы о нем знать. Хотя бы для общего развития :)

попробую уточнить у разработки, сообщу по результатам.

Валерий,

Программно запустить бизнес-процесс BPMonline можно через веб-сервис. Более подробно об этом изложено в статье SDK http://www.terrasoft.ua/bpmonlinesdk/WorkWithBpmByWebServices.html

Коллеги посоветовали :)

var manager = UserConnection.ProcessSchemaManager;
var processSchema = manager.GetInstanceByName("MyProcess");
var process = processSchema.CreateProcess(UserConnection);
if (processSchema.Parameters.ExistsByName("MyParameter")) {
process.SetPropertyValue(“MyParameter”, “value”);
}
process.Execute(Page.UserConnection);

приятно работы :)

Коллеги, огромное спасибо за помощь! Все работает.

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

Например, пользователь Вася зашел в BPM. Работает... Поступает входящий звонок от клиента на АТС, АТС в свою очередь направляет звонок на Васю.

При этом АТС смотрит по номеру телефона есть ли такой контакт в BPM. Если есть, то отправляет API команду в BPM "открыть карточку контакта с таким-то id", если нет такого клиента в базе, то открыть карточку "карточка нового контакта".

Надеюсь, понятно объяснил.
Есть ли подобный механизм управления BPM через API команды?

Нравится

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

??? Так же можно открыть карточку нужно контакта по URL, таким образом, что мы не знаем ID контакта,а только номер телефона??? При этом запрограммировать террасофт, что если он не нашел номер телефона, то карточка нового контакта, если нашел, то открывает карточку контакта.

Например, http://192.168.1.250:8080/....tel=89130000101

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

В ДОМ-моделе страницы BPMonline есть CTI панель. Ее сервис коммуницирует с ATC посредством WEB-Socket. При постплении входящего звонка АТС по WEB-Socket отправляет событие в браузер, тот в свою очередь, шлет запрос в сервер приложения IIS (на котором развернут web-сайт конфигурации).

Oktell работает по web-сокет. Возможна работа с октелл или придется что-то дописывать?
И с какой версии доступен данный функционал?

Илья, поддержка Oktell появится возможно в одной из будущих версий BPMonline. Пока затрудняюсь назвать сроки. Для поддержки нужно реализовывать приложение-коннеткор. Работа TAPI была реализована уже в версии BPMonline 5.2.0 ServiceDesk.

А не через TAPI. Например, через HTTP XML интерфейс есть какие-либо решения?

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

Полагаю, тут основной минус - скорость получения информации и ее достоверность.
WEB-socket на уровне прилложения надежнее и гораздо быстрее, т.к. работа ведется с объектами в ОЗУ.
XML - это также доступ к файловой сстеме, а с случае обработки сотни или несколько сотен таких файлов - вероятность потери данных резко возрастет - это мое видение ситуации.

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

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

Показать все комментарии
Публикация

Оказывается это возможно. Для этих целей можно воспользоваться библиотекой dynwrap.dll (сайт-источник: http://ourworld.compuserve.com/homepages/Guenter_Born/WSHBazaar/WSHDynaC...).

Что необходимо сделать:
1. Скачать архив (см. "Прикрепленные файлы" или по след. ссылке http://ourworld.compuserve.com/homepages/Guenter_Born/WSHBazaar/dynawrap...)

2. Распаковать его, скопировать dynwrap.dll в "C:\WINDOWS\system32" и зарегистрировать библиотеку:
regsvr32.exe "C:\WINDOWS\system32\dynwrap.dll"

3. В скрипте пишем след. код (в этом примере я объявляю API-функцию ShellExecute)

Wrap = System.CreateObject("DynamicWrapper");
Wrap.Register("SHELL32.DLL", "ShellExecute", "i=lssssl", "f=s", "r=l");

4. Использовать зарегистрированный метод ShellExecute следует так:

// Делаем окну SW_HIDE
Wrap.ShellExecute(Window.Handle, '', '', '', '', 0);

// А вот так минимизируем окно
Wrap.ShellExecute(Window.Handle, '', '', '', '', 6);

Более детальная информация по dynwrap.dll с примерами использования: http://www.script-coding.info/dynwrap.html.

Нравится

Поделиться

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

Не смог использовать на Windows 7 x64.

Полезная ссылка по этому поводу
http://www.script-coding.com/dynwrap.html

У меня остался только вопрос как возвращать апишные структуры из API в JS (например RECT из GetWindowReсt)
Пробовал бегло - не получилось. Но решение должно быть

"Alexandr Kravchuk" написал:Не смог использовать на Windows 7 x64.

А в чём проблема была? Если в регистрации dll, то это может помочь?

Добрый день.
Существует библиотека mydll.dll с функцией
int VerifyParams([In] string aa, [In, Out] StringBuilder bb, [Out] uint cc);

Пытаюсь объявить ее как:
Wrap.Register("mydll.dll", "VerifyParams", "i=srr", "f=s", "r=l");

Вызываю:
var AA = "123";
var Error = Wrap.VerifyParams(AA, BB, CC);

Error благополучно меняет значение в зависимости от значения АА. A вот BB и CC остаются неизменными...

Что то делаю не так?
Немного даже уточню вопрос. Все получается замечательно если функция возвращает один параметр. В моем случае возвращаются несколько параметров (Error, BB, CC). Dynwrap это вроде должен позволять судя по примеру про окно получения текста(http://www.script-coding.com/dynwrap.html), но пока не выходит на java. Действительно ли можно возвращать несколько параметров?

Здравствуйте, Виктор.

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

"Олейник Дмитрий" написал:Если в данном максимально упрощенном варианте функции будет возвращен только первый параметр - значит,данная библиотека не поддерживает возвращение нескольких параметров.

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

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

Добрый день!

"Олейник Дмитрий" написал:Попробуйте создать наиболее простую функцию

К сожалению это закрытая библиотека стороннего разработчика.

"Зверев Александр" написал:решением будет написание полноценной COM-dll

По такому сценарию видимо и будем решать проблему. Жаль что не получилось проще.

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