Добрый день!

Необходимо произвести настройку (интеграцию) системы с телефонией mango-office.ru. Ищу помощника, ТЗ пришлю.

 

Нравится

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

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

При удалении одной записи методом DataService с указанием фильтра по  колонке "id" время обработки запроса составляет 20-40 секунд, и это при общем количестве записей таблицы менее 1000. 

 При указании фильтра по любому строковому полю этого-же объекта(не индексируемому полю) , запрос отрабатывает существенно быстрее. 

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

Версия облачная, postgre, доступ к инструментам мониторинга отсутствует.

 

Пример запроса:

{"items": [

        {"__type": "Terrasoft.Nui.ServiceModel.DataContract.DeleteQuery","QueryId":1,"QueryType":1,

                        "Filters":{"FilterType":1,"ComparisonType":3,"LeftExpression":{"ExpressionType":0,"ColumnPath":"Id"},"RightExpression":

                        {"ExpressionType":2,"Parameter":{"DataValueType":0,"Value":"81a45c46-f8df-4913-83ac-1457399f3873"}}},"RootSchemaName":"Account","OperationType":0,"IncludeProcessExecutionData":false}

        ]}

Пробовал в разных интерпретациях параметров фильтра, результат не меняется.

 

 

 

Нравится

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

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

Не совсем понятна суть вопроса, что вам необходимо сделать?

Если вы пользуетесь DataService, то рекомендую ознакомиться с примером удаление записи с его помощью.

https://academy.terrasoft.ua/docs/developer/integrations_and_api/data_s…

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

Подскажите пожалуйста, не сделали еще поддержку работы jwt-токенов (внешний сервис аутентификации/авторизации)?

Нравится

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

Добрый день, Вадим!

 

Касательно вопроса аутентификации, на текущий момент из готовых реализаций у нас есть два способа аутентификации: базовая (логин/пароль) и OAuth 2.0. Для использования же  jwt-токенов необходимо писать пользовательские методы аутентификации, что требует навыков разработчика.

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



Спасибо, что помогаете делать наш продукт лучше!



С уважением,

Сидько Елена

Оператор

Группа компаний Terrasoft

 

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

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

 

Как изменить это поведение. Нужно чтобы попадало только если поле пустое.

 

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

Нравится

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

Ух, у меня получилось только костылями это решить. Возможно пригодится этот код, или возьмете идеи из него. Работает только с email контактов.

 

Создать замещающий объект ContactCommunication, Добавить новое логическое поле UsrIsPrimary в объект (основное средство связи). Добавить в этом объекте код, которые перекроет коробочную логику. А еще нужно будет пробежаться скриптом по базе и добавить свойство UsrIsPrimary для тех email, которые сейчас находятся в контакте. Может быть есть более элегантный способ решить проблему, но в свое время я смог додуматься только до такого.

 public override void ActualizePrimaryState()
        {
            base.ActualizePrimaryState();
 
            var contactId = Entity.GetTypedColumnValue<Guid>("ContactId");
            var communicationTypeId = Entity.GetTypedColumnValue<Guid>("CommunicationTypeId").ToString();
            bool isCurrentTypeEmail = communicationTypeId.Equals(CommunicationTypeConsts.EmailId);
 
            var contactESQ = new EntitySchemaQuery(UserConnection.EntitySchemaManager, "Contact");
            contactESQ.AddAllSchemaColumns();
            var contact = contactESQ.GetEntity(UserConnection, contactId);
            bool emailChanged = contact.GetTypedColumnValue<bool>("UsrEmailChanged");
            string email = contact.GetTypedColumnValue<string>("Email");
            if (contact != null && isCurrentTypeEmail && (emailChanged || string.IsNullOrEmpty(email)))
            {
                Entity.SetColumnValue("UsrIsPrimary", true);
 
                var update = new Update(UserConnection, "ContactCommunication")
                .Set("UsrIsPrimary", Column.Parameter(false))
                .Where("UsrIsPrimary").IsEqual(Column.Parameter(true))
                .And("ContactId").IsEqual(Column.Parameter(contactId))
                .And("Id").IsNotEqual(Column.Parameter(contactId))
                .And("CommunicationTypeId").IsEqual(Column.Parameter(CommunicationTypeConsts.EmailId)
                );
                update.Execute();
            }
        }
 
        public virtual KeyValuePair<string, bool> GetPrimaryContactEmail(Guid contactId)
        {
            KeyValuePair<string, bool> result = new KeyValuePair<string, bool>(string.Empty, false);
            var esq = new EntitySchemaQuery(UserConnection.EntitySchemaManager, "ContactCommunication");
            esq.RowCount = 1;
            EntitySchemaQueryColumn nonActualColumn = esq.AddColumn("NonActual").OrderByAsc(1);
            EntitySchemaQueryColumn isPrimatyColumn = esq.AddColumn("UsrIsPrimary").OrderByDesc(2);
            EntitySchemaQueryColumn orderByDescColumn = esq.AddColumn("CreatedOn").OrderByDesc(3);
            EntitySchemaQueryColumn numberColumn = esq.AddColumn("Number");
            esq.Filters.Add(esq.CreateFilterWithParameters(FilterComparisonType.Equal, "Contact", contactId));
            esq.Filters.Add(esq.CreateFilterWithParameters(FilterComparisonType.Equal, "CommunicationType",
                CommunicationTypeConsts.EmailId));
            EntityCollection entityCollection = esq.GetEntityCollection(UserConnection);
            foreach (Entity entity in entityCollection)
            {
                return new KeyValuePair<string, bool>(entity.GetTypedColumnValue<string>(numberColumn.Name),
                     entity.GetTypedColumnValue<bool>(nonActualColumn.Name));
            }
            return result;
        }
 
        public override void SetNewContactCommunication() {
            var contactCommunicationId = Entity.GetTypedColumnValue<Guid>("Id");
            var contactId = Entity.GetTypedColumnValue<Guid>("ContactId");
			var contactESQ = new EntitySchemaQuery(UserConnection.EntitySchemaManager, "Contact");
			contactESQ.AddAllSchemaColumns();
			var contact = contactESQ.GetEntity(UserConnection, contactId);
			if (contact != null) {
				var communicationTypeId = Entity.GetTypedColumnValue<Guid>("CommunicationTypeId").ToString();
				var number = Entity.GetTypedColumnValue<string>("Number");
				var socialColumnValue = Entity.GetTypedColumnValue<string>("SocialMediaId");
				var isPrimary = Entity.GetTypedColumnValue<bool>("IsCreatedBySynchronization");
				var typeColumnName = string.Empty;
				var socialColumnName = string.Empty;
				switch (communicationTypeId) {
					case CommunicationTypeConsts.LinkedInId:
				 		typeColumnName = "LinkedIn";
						socialColumnName = "LinkedInId";
						break;
					case CommunicationTypeConsts.TwitterId:
						typeColumnName = "Twitter";
						socialColumnName = "TwitterId";
						break;
					case CommunicationTypeConsts.FacebookId:
						typeColumnName = "Facebook";
						socialColumnName = "FacebookId";
						break;
					case CommunicationTypeConsts.EmailId:
						typeColumnName = "Email";
						break;
					case CommunicationTypeConsts.SkypeId:
				 		typeColumnName = "Skype";
						break;
					case CommunicationTypeConsts.HomePhoneId:
						typeColumnName = "HomePhone";
						break;
					case CommunicationTypeConsts.MobilePhoneId:
						typeColumnName = "MobilePhone";
						break;
					case CommunicationTypeConsts.WorkPhoneId:
						typeColumnName = "Phone";
						break;
					case CommunicationTypeConsts.WebId:
						typeColumnName = "Web";
						break;
				}
				if (!typeColumnName.Equals(string.Empty)) {
					bool isCanEdit = GetCanEditColumn("Contact", typeColumnName);
					if (!isCanEdit) {
						return;
					}
					bool isCurrentTypeEmail = communicationTypeId.Equals(CommunicationTypeConsts.EmailId);
					bool isOldTypeEmail = OldCommunicationTypeId.ToString().Equals(CommunicationTypeConsts.EmailId);
					bool isCurrentTypeWeb = communicationTypeId.Equals(CommunicationTypeConsts.WebId);
					bool isNotEmailOrWeb = !isCurrentTypeEmail && !isCurrentTypeWeb;
					if (!(isCurrentTypeEmail || isOldTypeEmail) && !isNotEmailOrWeb) {
						return;
					}
					string currentContactCommunicationValue = contact.GetTypedColumnValue<string>(typeColumnName);
					var update = new Update(UserConnection, "Contact") as Update;
					if (isCurrentTypeEmail || isOldTypeEmail) {
							KeyValuePair<string, bool> kvp = GetPrimaryContactEmail(contactId);
							if(!currentContactCommunicationValue.Equals(kvp.Key)) {
								var currentEmail = contact.GetTypedColumnValue<string>("Email");
                                bool emailChanged = contact.GetTypedColumnValue<bool>("UsrEmailChanged");
                            if (string.IsNullOrEmpty(currentEmail) || emailChanged) {
									update.Set("Email", Column.Parameter(kvp.Key));
                                    update.Set("UsrEmailChanged", Column.Parameter(false));
                                }
							}
							update.Set("IsNonActualEmail", Column.Parameter(kvp.Value));
					}
					if (isNotEmailOrWeb) {
						if (!currentContactCommunicationValue.Equals(number) && isPrimary) {
							update.Set(typeColumnName, Column.Parameter(number));
							if (!socialColumnName.Equals(string.Empty)) {
								update.Set(socialColumnName, Column.Parameter(socialColumnValue));
							}
						} else if (!isOldTypeEmail) {
							return;
						}
					}
					update.Set("ModifiedOn", Column.Parameter(DateTime.UtcNow));
					update.Where("Id").IsEqual(Column.Parameter(contactId));
					update.Execute();
				}
			}
		}

 

Еще добавить в Contact поле UsrEmailChanged

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

        attributes: {              

                "UsrEmailChanged":

                {

                    dependencies: [

                        {

                            columns: ["Email"],

                            methodName: "emailChanged"

                        }

                    ]

                },

        },

    methods: {

            onEntityInitialized: function() {

                this.callParent(arguments);

                if(this.$UsrEmailChanged) {

                    this.$UsrEmailChanged = false;

                }

            },



            emailChanged: function() {

                this.$UsrEmailChanged = true;

            },

        },

Ух, у меня получилось только костылями это решить. Возможно пригодится этот код, или возьмете идеи из него. Работает только с email контактов.

 

Создать замещающий объект ContactCommunication, Добавить новое логическое поле UsrIsPrimary в объект (основное средство связи). Добавить в этом объекте код, которые перекроет коробочную логику. А еще нужно будет пробежаться скриптом по базе и добавить свойство UsrIsPrimary для тех email, которые сейчас находятся в контакте. Может быть есть более элегантный способ решить проблему, но в свое время я смог додуматься только до такого.

 public override void ActualizePrimaryState()
        {
            base.ActualizePrimaryState();
 
            var contactId = Entity.GetTypedColumnValue<Guid>("ContactId");
            var communicationTypeId = Entity.GetTypedColumnValue<Guid>("CommunicationTypeId").ToString();
            bool isCurrentTypeEmail = communicationTypeId.Equals(CommunicationTypeConsts.EmailId);
 
            var contactESQ = new EntitySchemaQuery(UserConnection.EntitySchemaManager, "Contact");
            contactESQ.AddAllSchemaColumns();
            var contact = contactESQ.GetEntity(UserConnection, contactId);
            bool emailChanged = contact.GetTypedColumnValue<bool>("UsrEmailChanged");
            string email = contact.GetTypedColumnValue<string>("Email");
            if (contact != null && isCurrentTypeEmail && (emailChanged || string.IsNullOrEmpty(email)))
            {
                Entity.SetColumnValue("UsrIsPrimary", true);
 
                var update = new Update(UserConnection, "ContactCommunication")
                .Set("UsrIsPrimary", Column.Parameter(false))
                .Where("UsrIsPrimary").IsEqual(Column.Parameter(true))
                .And("ContactId").IsEqual(Column.Parameter(contactId))
                .And("Id").IsNotEqual(Column.Parameter(contactId))
                .And("CommunicationTypeId").IsEqual(Column.Parameter(CommunicationTypeConsts.EmailId)
                );
                update.Execute();
            }
        }
 
        public virtual KeyValuePair<string, bool> GetPrimaryContactEmail(Guid contactId)
        {
            KeyValuePair<string, bool> result = new KeyValuePair<string, bool>(string.Empty, false);
            var esq = new EntitySchemaQuery(UserConnection.EntitySchemaManager, "ContactCommunication");
            esq.RowCount = 1;
            EntitySchemaQueryColumn nonActualColumn = esq.AddColumn("NonActual").OrderByAsc(1);
            EntitySchemaQueryColumn isPrimatyColumn = esq.AddColumn("UsrIsPrimary").OrderByDesc(2);
            EntitySchemaQueryColumn orderByDescColumn = esq.AddColumn("CreatedOn").OrderByDesc(3);
            EntitySchemaQueryColumn numberColumn = esq.AddColumn("Number");
            esq.Filters.Add(esq.CreateFilterWithParameters(FilterComparisonType.Equal, "Contact", contactId));
            esq.Filters.Add(esq.CreateFilterWithParameters(FilterComparisonType.Equal, "CommunicationType",
                CommunicationTypeConsts.EmailId));
            EntityCollection entityCollection = esq.GetEntityCollection(UserConnection);
            foreach (Entity entity in entityCollection)
            {
                return new KeyValuePair<string, bool>(entity.GetTypedColumnValue<string>(numberColumn.Name),
                     entity.GetTypedColumnValue<bool>(nonActualColumn.Name));
            }
            return result;
        }
 
        public override void SetNewContactCommunication() {
            var contactCommunicationId = Entity.GetTypedColumnValue<Guid>("Id");
            var contactId = Entity.GetTypedColumnValue<Guid>("ContactId");
			var contactESQ = new EntitySchemaQuery(UserConnection.EntitySchemaManager, "Contact");
			contactESQ.AddAllSchemaColumns();
			var contact = contactESQ.GetEntity(UserConnection, contactId);
			if (contact != null) {
				var communicationTypeId = Entity.GetTypedColumnValue<Guid>("CommunicationTypeId").ToString();
				var number = Entity.GetTypedColumnValue<string>("Number");
				var socialColumnValue = Entity.GetTypedColumnValue<string>("SocialMediaId");
				var isPrimary = Entity.GetTypedColumnValue<bool>("IsCreatedBySynchronization");
				var typeColumnName = string.Empty;
				var socialColumnName = string.Empty;
				switch (communicationTypeId) {
					case CommunicationTypeConsts.LinkedInId:
				 		typeColumnName = "LinkedIn";
						socialColumnName = "LinkedInId";
						break;
					case CommunicationTypeConsts.TwitterId:
						typeColumnName = "Twitter";
						socialColumnName = "TwitterId";
						break;
					case CommunicationTypeConsts.FacebookId:
						typeColumnName = "Facebook";
						socialColumnName = "FacebookId";
						break;
					case CommunicationTypeConsts.EmailId:
						typeColumnName = "Email";
						break;
					case CommunicationTypeConsts.SkypeId:
				 		typeColumnName = "Skype";
						break;
					case CommunicationTypeConsts.HomePhoneId:
						typeColumnName = "HomePhone";
						break;
					case CommunicationTypeConsts.MobilePhoneId:
						typeColumnName = "MobilePhone";
						break;
					case CommunicationTypeConsts.WorkPhoneId:
						typeColumnName = "Phone";
						break;
					case CommunicationTypeConsts.WebId:
						typeColumnName = "Web";
						break;
				}
				if (!typeColumnName.Equals(string.Empty)) {
					bool isCanEdit = GetCanEditColumn("Contact", typeColumnName);
					if (!isCanEdit) {
						return;
					}
					bool isCurrentTypeEmail = communicationTypeId.Equals(CommunicationTypeConsts.EmailId);
					bool isOldTypeEmail = OldCommunicationTypeId.ToString().Equals(CommunicationTypeConsts.EmailId);
					bool isCurrentTypeWeb = communicationTypeId.Equals(CommunicationTypeConsts.WebId);
					bool isNotEmailOrWeb = !isCurrentTypeEmail && !isCurrentTypeWeb;
					if (!(isCurrentTypeEmail || isOldTypeEmail) && !isNotEmailOrWeb) {
						return;
					}
					string currentContactCommunicationValue = contact.GetTypedColumnValue<string>(typeColumnName);
					var update = new Update(UserConnection, "Contact") as Update;
					if (isCurrentTypeEmail || isOldTypeEmail) {
							KeyValuePair<string, bool> kvp = GetPrimaryContactEmail(contactId);
							if(!currentContactCommunicationValue.Equals(kvp.Key)) {
								var currentEmail = contact.GetTypedColumnValue<string>("Email");
                                bool emailChanged = contact.GetTypedColumnValue<bool>("UsrEmailChanged");
                            if (string.IsNullOrEmpty(currentEmail) || emailChanged) {
									update.Set("Email", Column.Parameter(kvp.Key));
                                    update.Set("UsrEmailChanged", Column.Parameter(false));
                                }
							}
							update.Set("IsNonActualEmail", Column.Parameter(kvp.Value));
					}
					if (isNotEmailOrWeb) {
						if (!currentContactCommunicationValue.Equals(number) && isPrimary) {
							update.Set(typeColumnName, Column.Parameter(number));
							if (!socialColumnName.Equals(string.Empty)) {
								update.Set(socialColumnName, Column.Parameter(socialColumnValue));
							}
						} else if (!isOldTypeEmail) {
							return;
						}
					}
					update.Set("ModifiedOn", Column.Parameter(DateTime.UtcNow));
					update.Where("Id").IsEqual(Column.Parameter(contactId));
					update.Execute();
				}
			}
		}

 

Еще добавить в Contact поле UsrEmailChanged

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

        attributes: {              

                "UsrEmailChanged":

                {

                    dependencies: [

                        {

                            columns: ["Email"],

                            methodName: "emailChanged"

                        }

                    ]

                },

        },

    methods: {

            onEntityInitialized: function() {

                this.callParent(arguments);

                if(this.$UsrEmailChanged) {

                    this.$UsrEmailChanged = false;

                }

            },



            emailChanged: function() {

                this.$UsrEmailChanged = true;

            },

        },

Мы дополнение сделали, возможно, кому-то пригодится

https://marketplace.terrasoft.ru/template/upravlenie-osnovnymi-sredstva…

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

Добрый день,

 

необходимо установить Exchange Listener для срм creatio.

 

Пробовали установить только с докером по этой инструкции https://academy.terrasoft.ru/docs/user/ustanovka_i_administrirovanie/ra… -- работают только старые версии. Не очень интересно.

 

Пробовала по этой инструкции поставить через Kubernetes

https://community.terrasoft.ru/articles/1-realnyy-primer-po-razvertyvan…

 

первое что меня смутило. У меня 20.04 (focal), а репозиторий для 16.04

" Next, we'll add the Kubernetes package repository. Note that at the time of this writing, Ubuntu 16.04 Xenial Xerus is the latest Kubernetes repository available. This should eventually be superseded by Ubuntu 20.04 Focal Fossa, and the following command can then be updated from xenial to focal. " Но его там нет. Этот работает, но под 16.04

deb http://apt.kubernetes.io/ kubernetes-xenial main

Второе, что не работают репозитории. Можно найти заменить. Не проблема.

helm repo add bitnami https://charts.bitnami.com/bitnami

 

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

 

 

wget https://get.helm.sh/helm-v3.6.0-rc.1-linux-amd64.tar.gz

 

helm install --namespace default --set usePassword=false --set=slave.persistence.enabled=false --set master.persistence.enabled=false --set cluster.enabled=false redis bitnami/redis

 

wget https://academy.creatio.com/sites/default/files/documents/downloads/Exc…

 

 

$ kubectl get pods

NAME               READY   STATUS             RESTARTS   AGE

elistener-api-0    0/1     CrashLoopBackOff   59         4h57m

redis-master-0     1/1     Running            0          4h58m

redis-replicas-0   0/1     Pending            0          4h58m

 

$  kubectl get service

NAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE

elistener-api    NodePort    10.109.70.15            80:30001/TCP   6m14s

kubernetes       ClusterIP   10.96.0.1               443/TCP        11m

redis-headless   ClusterIP   None                    6379/TCP       7m

redis-master     ClusterIP   10.96.133.113           6379/TCP       7m

redis-replicas   ClusterIP   10.102.18.199           6379/TCP       7m

 

$ kubectl get pods -o wide

NAME               READY   STATUS             RESTARTS   AGE     IP           NODE            NOMINATED NODE   READINESS GATES

elistener-api-0    0/1     CrashLoopBackOff   5          5m46s   10.244.0.5   r-creatio-lel             

redis-master-0     1/1     Running            0          6m32s   10.244.0.4   r-creatio-lel             

redis-replicas-0   0/1     Pending            0          6m32s                              

 

 

 

Events:

  Type     Reason     Age                From               Message

  ----     ------     ----               ----               -------

  Normal   Scheduled  91s                default-scheduler  Successfully assigned default/elistener-api-0 to r-creatio-lel

  Normal   Pulling    90s                kubelet            Pulling image "bpmonline/exchangelistener:0.8.39"

  Normal   Pulled     75s                kubelet            Successfully pulled image "bpmonline/exchangelistener:0.8.39" in 15.036026467s

  Warning  BackOff    32s (x2 over 37s)  kubelet            Back-off restarting failed container

  Normal   Created    17s (x3 over 75s)  kubelet            Created container exchangelistener

  Normal   Pulled     17s (x2 over 56s)  kubelet            Container image "bpmonline/exchangelistener:0.8.39" already present on machine

  Normal   Started    16s (x3 over 74s)  kubelet            Started container exchangelistener

 

 

2021-06-21 09:10:07,405 [1] FATAL: Application startup exception

StackExchange.Redis.RedisConnectionException: It was not possible to connect to the redis server(s). There was an authentication failure; check that passwords (or client certificates) are configured correctly. AuthenticationFailure (None, last-recv: 310) on 10.96.133.113:6379/Interactive, Flushed/ComputeResult, last: ECHO, origin: SetResult, outstanding: 0, last-read: 0s ago, last-write: 0s ago, keep-alive: 60s, state: ConnectedEstablishing, mgr: 8 of 10 available, last-heartbeat: never, global: 14s ago, v: 2.1.58.34321

 

Нравится

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

Скажите пожалуйста, а как убрать

Старая синхронизация почты (OldEmailIntegrationFeature, выключена)

Кеш настроек почты (IsMailboxSyncSettingsCached)

 

и заменить на exchangeListener

https://community.terrasoft.ru/articles/1-realnyy-primer-po-razvertyvan…



ответил в комментах, что мне помогло  в вашем случае

после необходимо будет обновить сервис exchangeListener

https://community.terrasoft.ru/articles/obnovlenie-mikroservisa-exchang…

и только после настраивать синхронизацию на стороне crm

Dima Avdoshin,

 

спасибо. Эта проблема решена.

 

Но почему-то http://IP_ExhangeListerVM:30001/api/listeners/status выдает только

 

{
  "ServiceStatus": "Started",
  "version": "0.8.39",
  "connections": {}
}

 

 

в примере должен быть connections с массой параметров

 

:~$ kubectl logs elistener-api-0

2021-06-22 11:09:59,477 [1] WARN : Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container                                      is destroyed.

2021-06-22 11:10:08,770 [1] WARN : No XML encryptor configured. Key {9817fbd1-66c7-41d2-a0b1-464f19d4fbf9} may be persisted to storage in unencrypted form.

Hosting environment: Production

Content root path: /app

Now listening on: http://0.0.0.0:80

Application started. Press Ctrl+C to shut down.

 

:~$ kubectl logs elistener-api-1

2021-06-22 11:10:30,772 [1] WARN : Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container                                      is destroyed.

2021-06-22 11:10:39,866 [1] WARN : No XML encryptor configured. Key {6f72b855-266a-452c-b621-783b0cfb454b} may be persisted to storage in unencrypted form.

Hosting environment: Production

Content root path: /app

Now listening on: http://0.0.0.0:80

Application started. Press Ctrl+C to shut down.

 

 

:~$ sudo ls -l /root/.aspnet/

ls: cannot access '/root/.aspnet/': No such file or directory

 

Нет такой папки на диске или смотреть в кубе?

 

Екатерина Валерьевна,



Статус EXCHANGE LISTENER возвращается корректный. Дополнительные параметры появятся после создания подписки на микросервисе (по результату успешного добавления почтового ящика для синхронизации в систему).

Алёна Доля,

спасибо большое. А как добавить?

Екатерина Валерьевна,

добавить ящик вы можете согласно инструкции:https://academy.terrasoft.ru/docs/user/ustanovka_i_administrirovanie/na…

Скажите пожалуйста, а как убрать

Старая синхронизация почты (OldEmailIntegrationFeature, выключена)

Кеш настроек почты (IsMailboxSyncSettingsCached)

 

и заменить на exchangeListener

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

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

Но при открытии существующего документа система только предлагает сменить на более подходящий кейс

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

Как массово сменить таким документам кейсы, чтобы статус документа не изменился? В самом кейсе нет никаких действий (всё выполняется в БП) - настроены только переходы между статусами и сам набор статусов

Нравится

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

Добрый день!

С помощью базовых функций в интерфейсе массовое автоматическое изменения кейсов с сохранением текущего статуса невозможно. Вполне вероятно, что это можно реализовать с помощью средств разработки. Обратите внимание на пост с похожей проблемой: https://community.terrasoft.ru/questions/zapustit-obnovlennyy-keys

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

Ярослав Савицкий,

спасибо за разъяснения. Было бы здорово сделать системную настройку "Автоматически заменять кейс при отсутствии запущенных процессов или действий"

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

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

Нужна консультация.

У нас возникла необходимость обрабатывать большие коллекции Entity(изменять значение поля и обновлять) при этом что бы был задействован событийный слой.

Решили данным способом:

var bc = new BlockingCollection<Entity>();
// Наполнение коллекции
.....
Parallel.ForEach(bc, new ParallelOptions {
   MaxDegreeOfParallelism = Environment.ProcessorCount
}, entity => entity.UpdateInDB(false));

Вопрос в следующем будем ли мы ловить локи при использовании UserConnection entity, не создавая нового?

Подобные случаи с локами были на версии 7.8.


 

Нравится

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

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

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

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

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

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

Или может как-то вынести поле с обращением, чтобы нажать и перейти.

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

Версия 7.18

Нравится

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

Добрый день!

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

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

 

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

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

Какие-нибудь дашборды или графики?

Спасибо.

Нравится

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

Добрый день.

На текущий момент подобный функционал отсутствует в приложении Creatio. 

Предположительно, через несколько версий, появится нечто подобное.

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

Добрый день.

На текущий момент подобный функционал отсутствует в приложении Creatio. 

Предположительно, через несколько версий, появится нечто подобное.

Владимир Соколов,

Спасибо.

Также, если сайт развернут on-site, то можно с помощью инструментов отладки запросов СУБД анализировать длительность выполнения запросов. Например, для MS SQL это SQL Profiler.

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

Добрый день.

Есть некий процесс. На развилке "ИЛИ" надо направить на разные ветки в зависимости от роли ответственного.

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

Пользователь может состоять в нескольких ролях. По трассировке я их получаю.

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

Как мне написать формулу в условном потоке чтобы выбрать роль и процесс пошел в определенную ветку?

Нравится

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

Доброе утро.

 

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

 

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

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

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