Добрый день. Необходимо написать функцию, которая подсчитывает количество значений в записи. Проблема в том, что из-за того что esq выполняется асинхронно, функция всегда возвращает undefined. Нужно как-то вернуть из нее значение, так как функция будет использоваться повторно. Как это пофиксить? Спасибо.
/**
* Подсчет количества продуктов в детали.
*/
checkProductsCount: function() {
var select = this.Ext.create("Terrasoft.EntitySchemaQuery", {
rootSchemaName: "OpportunityProductInterest"
});
var esqRestaurantFilter = Terrasoft.createColumnFilterWithParameter(
Так же вы можете столкнуться с тем, что в callback'е от вызова функции getEntityCollection не будет доступа к полям (на самом деле просто другой контекст в this будет), в этом случае следует перед выполнением запроса записать this в другую переменную:
var self = this.
var self =this;//ну и далее
var selectedProductsCount = select.getEntityCollection(function(result){if(result && result.success){
self.set("Filed", value);}}, this);
Так же вы можете столкнуться с тем, что в callback'е от вызова функции getEntityCollection не будет доступа к полям (на самом деле просто другой контекст в this будет), в этом случае следует перед выполнением запроса записать this в другую переменную:
var self = this.
var self =this;//ну и далее
var selectedProductsCount = select.getEntityCollection(function(result){if(result && result.success){
self.set("Filed", value);}}, this);
Подскажите как динамически делать пункт меню в "Действие" карточки в совмещенном режиме.
В обычном режиме все работает нормально.
attributes:{"IsCanVisaStatus":{
dataValueType: Terrasoft.DataValueType.BOOLEAN,
value:true, // Значение по умолчанию которое передаеться при загрузке страницы на нашу кнопку
dependencies:[{
columns:["KtState"], // Отслеживаем изменение поля состояния
methodName:"setCanVisaStatusContract"// и запускаем нашу функция если состояние изменчется}]}},
methods:{
onEntityInitialized: function(){this.callParent(arguments);this.setCanVisaStatusContract();// Запускаем функцию при входе на страницу когда поля уже заполненны},
getActions: function(){
var actionMenuItems =this.callParent(arguments);
actionMenuItems.addItem(this.getButtonMenuItem({
Type:"Terrasoft.MenuSeparator",
Caption:""}));
actionMenuItems.addItem(this.getButtonMenuItem({"Caption": VisaHelper.resources.localizableStrings.SendToVisaCaption,
"Tag": VisaHelper.SendToVisaMenuItem.methodName,
"Enabled":{"bindTo":"IsCanVisaStatus"}// мониторим через привязку состояние значения атрибута}));return actionMenuItems;},
setCanVisaStatusContract: function(){
var stateId =this.get("KtState").value;// Текущая стадия
var esq =this.Ext.create("Terrasoft.EntitySchemaQuery", {// Запрос к базе данных о том нужна ли кнопка отправки на визирования
rootSchemaName:"KtContractKarTelState"});
esq.addColumn("KtCanVisa", "KtCanVisa");// Сама колонка указывающая что нужна кнопка
esq.getEntity(stateId, function(result){if(result.success){if(result.entity.get("KtCanVisa")&&this.canEntityBeOperated()){// this.canEntityBeOperated() - стандартный класс отвечает за то что если карточка на в режиме редактирования то false.this.set("IsCanVisaStatus", true);}else{// Присваивает атрибуту значение true или false в зависимости от результата запросаthis.set("IsCanVisaStatus", false);}}}, this);}}
В отоге весь код работает хорошо но только в обычном режиме карточки, а совмещенном кнопка не видет атрибут хоть по девагу все запускается так же и значения поля в атрибуте меняется по кнопка просто его не видит. Пробовал атрибут вписать в Section - не помогло, атрибут видит кнопка но изменить его не получается.
Нужно использовать механизм сообщений. Вот пример. Моем случае бинд был на аттрибут (в странице редакирования) "Enabled": {"bindTo": "enabledPlanPaymentDate"}
Нужно использовать механизм сообщений. Вот пример. Моем случае бинд был на аттрибут (в странице редакирования) "Enabled": {"bindTo": "enabledPlanPaymentDate"}
Добрый день. Подскажите пожалуйста, не как не могу решить данный кейс (причем когда-то такой решал давно но не могу не как вспомнить как).
Есть кнопка в группе кнопок "Действие" - "Отправить на визирование", она запускает процесс визирования. Данная кнопка должна быть активна если в таблице визирования уже есть как минимум одна положительная запись (автор согласовал). Для этого сделал запрос к базе данных и получил результат. Через свойство "Enabled" нужно реализовать доступность кнопки.
решил вопрос через создание в таблице процесса что срабатывал при изменении в ней и отправлял сообщение на фронт, а на фронте подписался на него и запускаю функцию что меняет атрибут который и дает ответ в каком состоянии должна быть кнопка. Могу написать код реализации тут если кому нужно. Но в итоге бизнес решил что им это не надо потому далее не оптимизировал код. Сейчас проблема в активности этой кнопки в совмещенном режиме, создал отдельный вопрос
Возможно ли настроить конфигурацию мобильного приложения следующим образом, что бы при срабатывании бизнес правила и обработки модели текущей записи возможно было доставать значения данных из связанных записей? В данном случае меня интересует Контакт - http://prntscr.com/o5yxe7. Без написания запроса. или запрос нужно писать в любом случае? Стоит задача при изменении Контакта необходимо в заказе перезаписывать контактный номер телефона, как лучше реализовать?
Стоит задача при изменении Контакта необходимо в заказе перезаписывать контактный номер телефона, как лучше реализовать?
Мне кажется, такое нужно делать не в мобильной версии, а на стороне сервера при синхронизации. Ведь новые данные контакта могут прийти с разных сторон, например, их может исправить пользователь, работающий в веб-версии, интеграция с сайтом, 1С или ещё чем-то. Если менять будут при помощи класса EntitySchemaQuery, можно реализовать логику во встроенном или обычном процессе.
да это понятно на стороне сервера это само собой я предлагал и говорил заказчику, но требуют что бы на моб. устройстве все происходило, они будут работать в режиме оффлайн
Получены данные из БД отфильтровав их и сравнив с полученным значением из системной настройки ранее, и если значение выпадающего списка periodicity равно "Ежедневно" и количество записей в базе больше чем системной настройке - срабатывает валидация на поле и всплывающее уведомление при попытке сохранения:
message - сообщение для поля валидации;
periodicity - выпадающий список (словарь) в котором есть значение "Ежедневно";
countSettings - ранее полученное значение системной настройки;
concertProgramsCount - количество записей в таблице;
var periodicity ="";if(this.get("PsPeriodicity")){
periodicity =this.get("PsPeriodicity").displayValue;}
var esq = Ext.create("Terrasoft.EntitySchemaQuery", {
rootSchemaName:"PsConcertPrograms"});
esq.addColumn("PsPeriodicity.Name", "PsPeriodicityName");
var esq1Filter = esq.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,
"PsPeriodicity.Name", "Ежедневно");
esq.filters.add("esq1Filter", esq1Filter);
esq.getEntityCollection(function(result){
var message ="";if(result.success){
var concertProgramsCount = result.collection.collection.length;if(periodicity ==="Ежедневно"&& concertProgramsCount <= countSettings ){
message =this.get("Resources.Strings.PsFewFreeConcertHalls").replace("NNN", countSettings);}}return message;}, this);
Вывод валидации для поля и при сохранении страницы:
Проблема в том что по отдельности все работает, но когда вместе - вступает в дело асинхронность и все идет не по очереди, а если использую через callback тогда застреваю на замыкании.
Спасибо всем кто окажет помощь в решении проблемы.
Каждый борется с асинхронностью своими средствами :)
Как вариант, можно вложить одно в другое: выполнять запросы по очереди, по мере получения ответа из БД. Например перенести вашу логику с esq запросом в колбэк системной настройки.
Если ваша функция должна возвращать какие-то значение, то из коллбэка это сделать не получится. В этом случае у вас уже должны быть где-то готовые значения для того, что бы функция валидации могла синхронно выполниться и вернуть значения. Например значение системной настройки можно получить при инициализации страницы и сохранить в атрибуте страницы, т.к. системная настройка скорее всего не будет часто меняться. Значение из esq запроса можно так же получить раньше и сохранить в атрибут, а потом уже при валидации оперировать существующими значениями. Ну или сделать так, как посоветовал Варфоломеев Данила.
В статье Асинхронные запросы в bpm’online 5.X был приведен пример отправки Get/Post запросов со страницы с использование языка JavaScript. В этой статье хотелось бы рассказать про подводные камни, которые встретились при реализации и как их можно обойти.
Предположим, имеется некий абонент интернет провайдера, у которого есть такие поля, как баланс, MAC-адрес, IP-адрес, состояние, список последних сессий абонента, получение доступных для смены тарифов, получение текущего тарифа абонента. При открытии карточки необходимо получать обновленную информацию от WCF сервиса, отображать её на странице и сохранять в базе данных.
При наличии сложной логики на странице, а именно:
применение нескольких асинхронных запросов;
обновление значений в контроллах на странице;
обновление значений столбцов в DataSource.ActiveRow;
обновление записей в базе с помощью класса Update (для того, чтобы при получении обновленной информации от сервиса, например, баланса, сразу записывать его значение в базу, и при последующем открытии карточки, даже если пользователь закрыл страницу не сохранив запись нажав "Отмена", пользователь увидит последние обновленные сведения, полученные от биллинговой системы, до того момента, пока от сервиса не придет новая, обновленная информация о балансе, в противном случае, при отсутствии доступа к данному сервису (пропало интернет соединение), будет отображаться последняя загруженная информация о балансе).
Столь сложная логика на странице может стать причиной ошибок на странице, как, например, ошибка "Сбой при загрузке состояния отображения. Дерево элементов управления, в которое загружается это состояние отображения, должно соответствовать дереву элементов управления, использованному для сохранения состояния отображения при предыдущем запросе. Например, при динамическом добавлении элементов управления те элементы управления, которые были добавлены при обратной передаче, должны по типу и положению соответствовать элементам управления, добавленным при исходном запросе." (скриншот окна с ошибкой ниже).
Данная ошибка возникает при переходе на деталь "Активности", и другие детали, в которые загружается информация, связанная с данной записью. Причем ошибка возникает только во время выполнения асинхронных запросов к сервису, если быть точнее, при получении информации от сервиса, выполняется серверная логика, во время которой и возникает ошибка.
Чтобы избежать данной ошибки, необходимо запретить пользователю переходить на детали, которые вызывают ошибку. Сделать это можно следующим образом.
В БП страницы на событие PageLoadComplete необходимо добавить элемент "Задание сценарий", который добавляет на страницу следующий JavaScript код (данный скрипт должен выполняться перед добавлением скрипта создания самого запроса, т.е. объекта XMLHttpRequest, как было описано в статье):
// Функция, позволяющая скрыть/отобразить все детали, следующие за деталью // "Активности", включая саму эту деталь function changeVisibleOfTabs(isVisible){ for(var i =0; i PageContainer_DataTabPanel.items.items.length; i++){ if(PageContainer_DataTabPanel.items.items[i].caption=='Активности'){ for(var j = i; j PageContainer_DataTabPanel.items.items.length; j++){
PageContainer_DataTabPanel.items.items[j].tabHeader.setVisible(isVisible); } break; } } }
// скрываем детали перед выполнением запросов
changeVisibleOfTabs(false);
// создаем таймер, который каждые 500мс проверяет, завершились ли все запросы, // после того, как все запросы завершены, создаем таймер на 2000мс, // чтобы отработала вся логика на странице, после чего отображаем скрытые детали var timerCheckIsDone = setInterval(function(){ if((requestUpdateBalance != undefined && requestUpdateBalance !=null&& requestUpdateBalance.readyState==4)&& (requestUpdateMacAndSerialNumber != undefined && requestUpdateMacAndSerialNumber !=null&& requestUpdateMacAndSerialNumber.readyState==4)&& (requestUpdateAbonentState != undefined && requestUpdateAbonentState !=null&& requestUpdateAbonentState.readyState==4)&& (requestGetSessionDetalisation != undefined && requestGetSessionDetalisation !=null&& requestGetSessionDetalisation.readyState==4)&& (requestGetAvaliableTariffs != undefined && requestGetAvaliableTariffs !=null&& requestGetAvaliableTariffs.readyState==4)&& (requestGetCurrentTariff != undefined && requestGetCurrentTariff !=null&& requestGetCurrentTariff.readyState==4)){
clearInterval(timerCheckIsDone); var timerChangeVisibleOfTabs = setTimeout(function(){
changeVisibleOfTabs(true);// отображаем детали },2000); } },500);
Важно! После выполнения данного скрипта, необходимо создать объекты запросов, как было показано в статье. Причем объекты запросов должны ссылаться на глобальные переменные, которые мы объявляли в самом начале, т.е. необходимо писать вместо
var request = new XMLHttpRequest();
вот так:
requestUpdateBalance = new XMLHttpRequest();
Иначе доступ к данным переменным будет невозможен из функции, где выполняется проверка завершения запросов.
Есть ситуации, когда нужно, чтобы при открытии карточки редактирования, в поля карточки подгружалась информация, которую нужно выводить в актуальном (обновленном) состоянии. К примеру, когда клиент звонит в тех поддержку, сотрудник техподдержки открывает карточку клиента в bpm'online и должен видеть текущий баланс данного клиента. Предположим, есть WCF сервис, работающий на некотором хостинге, созданный для интеграции с биллинговой системой, с методом получения баланса абонента GetBalance, ответ от которого приходит в виде строки в формате JSON, который мы можем обработать и вывести в нужном формате на страницу редактирования.
Если выполнять запрос из бизнес процесса карточки редактирования (на PageLoadComplete, к примеру), то при выполнении запроса возникает зависание карточки редактирования, и она не отвиснет пока либо не придет ответ, либо пока запрос не будет завершен по таймауту (если сервер долго не отвечает).
Чтобы выполнить запрос асинхронно, нужно добавить на страницу редактирования JavaScript код, который будет обращаться к сервису, получать ответ от него и выводить результат в контролы страницы. Чтобы отправлять запрос сразу после загрузки страницы, нужно добавить элемент бизнес процесса «Задание-сценарий» на событие «PageLoadComplete», либо если нужно отправлять запрос по нажатию на кнопку, то на событие нажатия на неё.
При выполнении данного кода Java Script кода на странице, мы получим ошибку в консоли браузера:
XMLHttpRequest cannot load http://someserveradress/SomeWCFService.svc/GetBalance. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.
Ошибка говорит о том, что запрещено обращаться к другому домену (попытка выполнить кросс-доменный запрос). Данное ограничение введено из соображений безопасности, но его можно обойти используя технологию CORS.
Подробную информацию об этой технологии можно посмотреть тут:
1) https://ru.wikipedia.org/wiki/Cross-origin_resource_sharing
2) http://enable-cors.org/
3) http://habrahabr.ru/post/120917/
Для того, чтобы разрешить кросс-доменные запросу, нужно включить поддержку на сервере, к которому приходит запрос, в моём случае это WCF служба. Для включения поддержки CORS у WCF сервиса, нужно выполнить действия, описанные тут: http://enable-cors.org/server_wcf.html.
Информацию по включению поддержки CORS для других платформ/серверов можно найти тут: http://enable-cors.org/server.html.
После этого, запрос должен выполняться асинхронно, не вызывая зависание карточки, благодаря чему можно просматривать/редактировать карточку в момент выполнения запроса.