Вопрос

Как убрать действие в мобильном приложении и как можно их отсортировать

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

Ответ

Примерный алгоритм.

1. Необходимо создать свой модуль (например «TestOrderRemoveMobileAccountModuleConfig»)

2. Для удаления действия необходимо использовать следующий метод - Terrasoft.sdk.Actions.remove: function(model, actionName)

 

Пример:

Terrasoft.sdk.Actions.remove("Account", "addAccountAnniversary");



3. Для сортировки нужно использовать:

Terrasoft.sdk.Actions.setOrder("model ", {
    "actionName1": 0,
    "actionName2": 1,
    …,
    "actionName5": 4
});

Пример:

Terrasoft.sdk.Actions.setOrder("Account", {
    "Phone": 0,
    "Email": 1,
    "Meeting": 2,
    "Terrasoft.ActionCopy": 3,
    "Terrasoft.ActionDelete": 4
});
 

4. Потом подключить в пользовательском манифесте мобильного приложения (можно ознакомиться на нашем SDK)  в секции «Models» для объекта «Account» (если это контрагенты) в разделе «PagesExtensions». Например:

"Models": {
    "Account": {
        "RequiredModels": [],
        "ModelExtensions": [],
        "PagesExtensions": [
            "TestOrderRemoveMobileAccountModuleConfig"
        ]
    },
 



где TestOrderRemoveMobileAccountModuleConfig – произвольное название схемы.

 

Реализацию логики добавления адреса можете посмотреть в схеме «MobileAccountModuleConfig» (действие называется «addAccountAddress»).

Нравится

Поделиться

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

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

Нет, при помощи Terrasoft SDK такой возможности нет.

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

Вопрос

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

Ответ

При сохранении объекта с портала, срабатывает процесс определенный в объекте Case пакета Портал,событие CaseInserting, в нем очищается Ответственный, если UserType = SSP.

Нравится

Поделиться

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

Вопрос

После обновления не применяются стили для иконок твиттера и фейсбука на детали "Средства связи"

Ответ

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

Для устранения проблемы необходимо перенести стили из базового модуля CommonCSSV2 в замещающий и в конце добавить обратно пользовательские стили. Также можно убрать текст из вкладки "Исходный код" модуля - стили, которые содержатся на этой вкладке, применяться не будут.

Нравится

Поделиться

0 комментариев
Показать все комментарии
//Добавляем атрибуты и методы
attributes: {
    "UsrDATE1": { //Поле куда будет записываться дата
        dataValueType: Terrasoft.DataValueType.DATE, //Тип поля в зависимости от типа поля UsrDATE1
        dependencies: [
            {
                columns: ["UsrDATE"], //Поле с первоначальной датой
                methodName: "calculatedate"
            }
        ]
    }
},
methods: {
    calculatedate: function() {
        var D6 = this.get("UsrDATE"); //Поле с первоначальной датой
        if (D6) {
            var D7 = new Date ();
            D7.setDate(D6.getDate() - 14); //14 количество дней, которые нужно отнять
            this.set("UsrDATE1", D7);
        }
    }
},

 

Нравится

Поделиться

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

Пример метода из статьи содержит ошибку, проверяется  вводом в первоначальную дату даты одного числа месяца, а затем вводом нового значения увеличенного на любое количество месяцев. Для корректного расчета  используйте  setTime и getTime для правильного отнимания  времени в милисекундах от первоначальной даты. Обновленный сalculatedate метод прилагаю ниже                                                сalculatedate: function() {

        var D6 = this.get("AccountClosingDate"); //Поле с первоначальной датой

        if (D6) {

            var D7 = new Date ();

            D7.setTime(D6.getTime() - (24*60*60*1000)); //24*60*60*1000 =1 день- количество дней, которые нужно отнять

            this.set("BalanceTransferDate", D7); //Поле где меняем дату от первоначальной

            this.save({isSilent: true}); //сохраняем

        }

    }, 

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

Вопрос

Скажите, как правильно вызвать веб-сервис созданный в одной bpm из сторонней bpm?

Получаю ошибку Cross-origin resource sharing.

Ответ

Все что будет сказано далее, тестировалось на своих тестовых площадках. Единственное что колонку в лиде, по которой будет производиться поиск, назвали с префиксом: UsrTest. И сами классы утилс, и сервиса, так же назвали с префиксами: UsrMyTestService, UsrLeadSearchUtils.

В итоге, на старте, у нас имеется:

Код схемы сервиса

namespace Terrasoft.Configuration.CustomConfigurationService
{
	using System;
	using System.Collections.Generic;
	using System.Runtime.Serialization;
	using System.Linq;
	using System.ServiceModel;
	using System.ServiceModel.Web;
	using System.ServiceModel.Activation;
	using System.Web;
	using System.IO;
	using Terrasoft.Core;
	using Terrasoft.Core.Configuration;
	using Terrasoft.Core.DB;
	using Terrasoft.Core.Entities;
 
	[ServiceContract]
	[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
	public class UsrMyTestService
	{
		private UserConnection _userConnection;
 
		private UserConnection UserConnection {
			get {
				return _userConnection ?? (_userConnection = HttpContext.Current.Session["UserConnection"] as UserConnection);
			}
		}
 
		[OperationContract]
		[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped,
			ResponseFormat = WebMessageFormat.Json)]
		public testclass myTestServiceFunction(string test)
		{
			//////
			var currentWebOperationContext = WebOperationContext.Current;
			var outgoingResponseHeaders = currentWebOperationContext.OutgoingResponse.Headers;
			var incomingRequestOrigin = currentWebOperationContext.IncomingRequest.Headers["Origin"];
			outgoingResponseHeaders.Add("Access-Control-Allow-Origin", incomingRequestOrigin);
			///////
			testclass result = new testclass();
			UsrLeadSearchUtils leadSearchUtil = new UsrLeadSearchUtils(this.UserConnection);
			try {
				var leadCollection = leadSearchUtil.SearchLeadByCustomerID(test);
				foreach (var item in leadCollection) {
					result.Response.Add(new SearchItem() {
						Id = item.GetTypedColumnValue<Guid>("LeadId"),
						Name = item.GetTypedColumnValue<string>("LeadName"),
					});
				}
			} catch (Exception ex) {
				result.Success = false;
				result.ErrorMessage = ex.Message;
			};
			return result;
		}
 
		////////
		[OperationContract]
		[WebInvoke(Method = "OPTIONS", UriTemplate = "SaveWebFormLeadData")]
		public void GetWebFormLeadDataRequestOptions() {
			var outgoingResponseHeaders = WebOperationContext.Current.OutgoingResponse.Headers;
			outgoingResponseHeaders.Add("Access-Control-Allow-Origin", "*");
			outgoingResponseHeaders.Add("Access-Control-Allow-Methods", "POST");
			outgoingResponseHeaders.Add("Access-Control-Allow-Headers", "Origin, Content-Type, Accept");
		}
		//////////
 
		[DataContract]
		public class testclass {
			public testclass() {
				this.Success = true;
				this.Response = new List<SearchItem>();
			}
			[DataMember]
			public List<SearchItem> Response {
				get;
				set;
			}
			[DataMember]
			public bool Success {
				get;
				set;
			}
			[DataMember]
			public string ErrorMessage {
				get;
				set;
			}
		}
 
		[DataContract]
		public class SearchItem {
			[DataMember]
			public Guid Id {
				get;
				set;
			}
			[DataMember]
			public string Name {
				get;
				set;
			}
		}
	}
}

Код схемы утилит

namespace Terrasoft.Configuration
{
	using System;
	using System.Collections.Generic;
	using System.IO;
	using Terrasoft.Core;
	using Terrasoft.Core.Configuration;
	using Terrasoft.Core.DB;
	using Terrasoft.Core.Entities;
 
	public class UsrLeadSearchUtils {
		public UsrLeadSearchUtils (UserConnection userConnection) {
			this.UserConnection = userConnection;
		}
 
		private UserConnection UserConnection {
			get;
			set;
		}
 
		public EntityCollection SearchLeadByCustomerID(string email) {
			if (string.IsNullOrEmpty(email)) {
				throw new ArgumentException("email is undefined.");
			}
 
			var entitySchemaManager = this.UserConnection.GetSchemaManager("EntitySchemaManager") as EntitySchemaManager;
			var esq = new EntitySchemaQuery(entitySchemaManager, "Lead");
			esq.RowCount = 20;
			esq.AddColumn("Id").Name = "LeadId";
			esq.AddColumn("LeadName").Name = "LeadName";
			esq.AddColumn("UsrTest").Name = "UsrTest";
			esq.Filters.Add(esq.CreateFilterWithParameters(FilterComparisonType.Equal, "UsrTest", 
				email));
 
			return esq.GetEntityCollection(this.UserConnection);
		}
	}
}

Сервис пробуем вызвать из той же bpm’online где сервис и создан, следующим образом:

onGetServiceInfoClick: function() {
    var usrTest = "test1";
    var serviceData = {
        test: usrTest
    };
    ServiceHelper.callService("UsrMyTestService", "myTestServiceFunction",
        function(response) {
            var result = response.myTestServiceFunctionResult;
            alert(result.Response[0].Name);
        }, serviceData, this
    );
}

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

Теперь давайте попробуем сделать запрос к этому сервису из другой bpm’online.

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

Правки в конфигах детальнее.

1) Вносим правки в наш «UsrMyTestService», помещаем его в немспейс «Terrasoft.Configuration», дописываем «UriTemplate» к методу, и опциям, наследуемся от «BaseService» а так же используем «SystemUserConnection» вместо обычного, так как авторизации не будет.

Результат:

namespace Terrasoft.Configuration
{
	using System;
	using System.Collections.Generic;
	using System.Runtime.Serialization;
	using System.Linq;
	using System.ServiceModel;
	using System.ServiceModel.Web;
	using System.ServiceModel.Activation;
	using System.Web;
	using System.IO;
	using Terrasoft.Core;
	using Terrasoft.Core.Configuration;
	using Terrasoft.Core.DB;
	using Terrasoft.Core.Entities;
	using Terrasoft.Web.Common;
 
	[ServiceContract]
	[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
	public class UsrMyTestService : BaseService
	{
		private SystemUserConnection _systemUserConnection;
		private SystemUserConnection SystemUserConnection {
			get {
				return _systemUserConnection ?? (_systemUserConnection = (SystemUserConnection)AppConnection.SystemUserConnection);
			}
		}
 
		[OperationContract]
		[WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped,
		ResponseFormat = WebMessageFormat.Json, UriTemplate = "myTestServiceFunction/{test}/")]
		public testclass myTestServiceFunction(string test)
		{
			///////
			var currentWebOperationContext = WebOperationContext.Current;
			var outgoingResponseHeaders = currentWebOperationContext.OutgoingResponse.Headers;
			var incomingRequestOrigin = currentWebOperationContext.IncomingRequest.Headers["Origin"];
			outgoingResponseHeaders.Add("Access-Control-Allow-Origin", incomingRequestOrigin);
			///////
			testclass result = new testclass();
			try {
				UsrLeadSearchUtils leadSearchUtil = new UsrLeadSearchUtils(this.SystemUserConnection);
				var leadCollection = leadSearchUtil.SearchLeadByCustomerID(test);
				foreach (var item in leadCollection) {
					result.Response.Add(new SearchItem() {
						Id = item.GetTypedColumnValue<Guid>("LeadId"),
						Name = item.GetTypedColumnValue<string>("LeadName"),
					});
				}
			} catch (Exception ex) {
				result.Success = false;
				result.ErrorMessage = ex.Message;
			};
			return result;
		}
 
		[OperationContract]
		[WebInvoke(Method = "OPTIONS", UriTemplate = "*")]
		public void GetWebFormLeadDataRequestOptions() {
			var outgoingResponseHeaders = WebOperationContext.Current.OutgoingResponse.Headers;
			outgoingResponseHeaders.Add("Access-Control-Allow-Origin", "*");
			outgoingResponseHeaders.Add("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
			outgoingResponseHeaders.Add("Access-Control-Allow-Headers", "Origin, Content-Type, Accept, X-Requested-With, X-Requested-With, x-request-source");
			outgoingResponseHeaders.Add("Access-Control-Request-Headers", "X-Requested-With, x-request-source, accept, content-type");
		}
 
		[DataContract]
		public class testclass {
			public testclass() {
				this.Success = true;
				this.Response = new List<SearchItem>();
			}
			[DataMember]
			public List<SearchItem> Response {
				get;
				set;
			}
			[DataMember]
			public bool Success {
				get;
				set;
			}
			[DataMember]
			public string ErrorMessage {
				get;
				set;
			}
		}
 
		[DataContract]
		public class SearchItem {
			[DataMember]
			public Guid Id {
				get;
				set;
			}
			[DataMember]
			public string Name {
				get;
				set;
			}
		}
	}
}

Класс утилит остается таким, как и был.

2) В папке сайта в котором написан наш сервис, *сайт*\Terrasoft.WebApp\ServiceModel

Создаем файл «UsrMyTestService.svc»

В содержимое файла пишем:

<%@ ServiceHost Language="C#" Debug="true" Service="Terrasoft.Configuration.UsrMyTestService" CodeBehind="UsrMyTestService.svc.cs" %>

3) В папке *сайт* \Terrasoft.WebApp в файле Web.config  рядом с другими локациями, добавляем:



   

     

         

     

   

4) В папке *сайт*\Terrasoft.WebApp\ в файле Web.config в секции appSettings меняем  значение ключа AllowedLocations. В значение добавляем:

ServiceModel/UsrMyTestService.svc;

5) В папке *сайт*\Terrasoft.WebApp\ServiceModel\http в файле services.config в блоке сервисов добавляем:



   

      address=""

      binding="webHttpBinding"

      behaviorConfiguration="RestServiceBehavior"

      bindingNamespace="http://Terrasoft.WebApp.ServiceModel"

      contract="Terrasoft.Configuration.UsrMyTestService" />

6) В папке *сайт*\Terrasoft.WebApp\ServiceModel\https в файле services.config в блоке сервисов делаем то же самое, что и в пункте 5.

Сервис будет доступен по адресу:

http(или https)://адрес-сайта/0/ServiceModel/UsrMyTestService.svc

В рамках теста, все выше сказанное было сделано на нашем локальном сайте:

http://localhost:8012/



Теперь для того что бы обратится к этому сервису с другого сайта, который на наших тестовых площадках находится по адресу:

http://localhost:8006/

Доработаем к примеру схему контакта следующим образом:

define("ContactPageV2", ["ContactPageV2Resources", "GeneralDetails", "JQuery"],
function(resources, GeneralDetails) {
	return {
		entitySchemaName: "Contact",
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		diff: /**SCHEMA_DIFF*/[
		]/**SCHEMA_DIFF*/,
		attributes: {},
		methods: {
 
			onEntityInitialized: function() {
				this.callParent(arguments);
				document.scp = this;
			},
 
			test: function() {
				var params = {
					test: "test1"
				};
				require(["jQuery"], function() {
					$.ajax({
						url: "http://localhost:8012/0/ServiceModel/UsrMyTestService.svc/myTestServiceFunction/" +
							params.test + "/",
						success: function(data) {
							alert(JSON.stringify(data));
						},
						error: function() {
							alert("Error occured!");
						}
					});
				});
			}
		},
		rules: {},
		userCode: {}
	};
});

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

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

 

Нравится

Поделиться

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

Вопрос

У клиента проблема с поиском дублей Контактов. Дубли система находит, карточку дублей открывает, а вот по нажатию кнопки «Сохранить» ничего не происходит.

Ответ

Проблема в том, что пользователь заместил объект «Contact» и поставил у него обязательным к заполнению поле «Email».

Если настройку снять, объединение дублей проходит без проблем.

Если же пользователю нужно будет запретить пользователям оставлять поле e-mail незаполненным, не повредив при этом базовую функциональность, это следует делать с помощью бизнес правил:

https://academy.terrasoft.ru/documents/technic-sdk/7-6/nastroyka-poley-stranicy-redaktirovaniya-s-pomoshchyu-biznes-pravil

 

Нравится

Поделиться

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

Вопрос

Построитель запросов при обращении с портала к таблице ServiceEngineer подставляет таблицу SysEmpty. вместо Service Engeneer. Запрос формируется в сервисе PortalCasePage.

Ответ

Для того, чтобы отрабатывали запросы к определенному объекту на портале, после включения прав для портальных пользователей, необходимо выполнить следующий скрипт:

insert into SysSSPEntitySchemaAccessList (EntitySchemaUId) values ('XXX')

где ХХХ – значение из колонки UId таблицы SysSchema, объекта «Сервисный инженер» в кастомном пакете.

Нравится

Поделиться

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

Вопрос

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

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

Ответ

Вам необходимо в конфигураторе, в схеме страницы вашего раздела добавить локализируемую строку и следующий код в блоке diff:

{
    "operation": "insert",
    "name": "UsrTestLabel",
    "values": {
        "layout": {
            "column": 12,
            "row": 0,
            "colSpan": 12,
            "rowSpan": 1
        },
        "itemType": Terrasoft.ViewItemType.LABEL,
        "caption": {
            "bindTo": "Resources.Strings.UsrTestLabelString"
        }
    },
    "parentName": "Header",
    "propertyName": "items"
},

Блок "layout" описывает положение и размер элемента на сетке.

Нравится

Поделиться

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

Симптомы

При установке bpm'online mobile 7 для Windows 10 ошибка "The error code is 0x803F7000"

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

Причина

Ошибка связана с локальными настройками Windows 10.

Причины ошибки:

  • Windows Store Cache.
  • Неверные данные и время.
  • Окна не активировали.
  • Microsoft Сервер перегружен.

Решение

Ссылки, в которых описана причина и решение данной проблемы:

-      http://answers.microsoft.com/en-us/windows/forum/windows_10-win_upgrade/error-code-0x803f7000-in-windows-store-10/18f61f6f-009a-435f-8d33-6956e301a849?auth=1

-      http://www.fixerrs.com/2015/09/fix-error-0x803f7000-windows-10-store.html

-      http://errortools.com/windows/how-to-fix-windows-10-error-code-0x803f7000/

-      http://microsoftfixnow.com/error-code-0x803f7000-windows-10-while-accessing-windows-store/

Нравится

Поделиться

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

Задача

Есть некий объект – положим, контрагент, у которого есть параметр 1, параметр 2, параметр 3. 

У этого объекта есть деталь, в которой отображаются записи этого же типа объекта, например, контрагенты, у которых выполняется условие «параметр 1 + параметр 2 соответствуют основной записи», «параметр 2 + параметр 3 соответствуют основной записи», «параметр 1 + параметр 3 соответствуют основной записи».

В детали можно фильтровать по нескольким колонкам. Но как сделать UNION,  т.е. «просуммировать» несколько таких независимых наборов фильтров? 

Решение

Допустим есть наполнение таблицы контрагент:

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

Следовательно, по выше написанному наполнение карточки и детали будет следующим:

1) Первый вариант наполнения детали;

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

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

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

«В детали можно фильтровать по нескольким колонкам. Но вот как сделать UNION,  т.е. «просуммировать» несколько таких независимых наборов фильтров?»

Если имелся в виду первый вариант наполнения детали, то filterGroup в методе фильтрации на карточке будет выглядеть следующим образом:

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

Если имелся в виду второй вариант наполнения детали, то filterGroup в методе фильтрации на карточке будет выглядеть следующим образом:

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

Также ошибка в добалении групп – не указаны их ключи. Правильное добавление групп:

filterGroup.add(1”, filterGroup1);
filterGroup.add(2”, filterGroup2);
filterGroup.add(3”, filterGroup3);

                                                           

Нравится

Поделиться

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