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

Нравится

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

Добрый день!

Если не нужно при этом генерировать сигналы объектов, то посоветую реализовать все в хранимой процедуре. Там уже реализовать цикл. Тем самым вы добьетесь максимальной производительности. А процедуру вызывать в скрипте C#.

Добрый день!

Если не нужно при этом генерировать сигналы объектов, то посоветую реализовать все в хранимой процедуре. Там уже реализовать цикл. Тем самым вы добьетесь максимальной производительности. А процедуру вызывать в скрипте C#.

Если доступа к серверу нет, то можно и без хранимок, используя в C#-скрипте БП классы Select и Update. С ними тоже сигналы не генерируются. А если нужно, чтобы по каждой записи отрабатывала логика встроенных и отдельных БП на изменение ответственного, то только с использованием класса EntitySchemaQuery.

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

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

 

Пробовал реализовать через esq: 

          var isOwnerInChange = true;

           while (isOwnerInChange) {

                var subQuery = new EntitySchemaQuery(_uc.EntitySchemaManager,"UsrChangeOwnerHelperLog");

                    subQuery.AddColumn("UsrEntityId");

    

                var entitySchemaManager = _uc.EntitySchemaManager;

                var esq = new EntitySchemaQuery(entitySchemaManager, "Название схемы");

                esq.UseAdminRights = false;

                esq.AddAllSchemaColumns();



              //  какие то фильтры

                

                var mainFilter = new EntitySchemaQueryFilter(FilterComparisonType.NotExists);

                    mainFilter.LeftExpression = esq.CreateSchemaColumnExpression("Id");

                    mainFilter.RightExpressions.Add(new EntitySchemaQueryExpression(subQuery));

                    esq.Filters.Add(mainFilter);

                

                esq.RowCount=1000;

                    

                var entities = esq.GetEntityCollection(_uc);

                

                if (entities.Count > 0)

                    {

                        foreach (Entity entity in entities)

                        {

                            var entityId = entity.GetTypedColumnValue<Guid>("Id");

                            var newOwnerId = SearchOwner(accountId, "Account");



                            //Какая то логика

                        }

                } else {

                    isOwnerInChange = false;

                }

            }

В конце не забудьте каждой entity.Save();

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

Добрый день !

Есть ли возможность без программирования направлять пользователю на электронную почту уведомление (допустим по пятницам или по понедельникам)  - чтобы в теле письма была таблица со всеми лидами, созданными за прошедшую неделю (желательно кликабельные ссылки)? Как можно это реализовать ?

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

Нравится

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

Добрый день!

Выполнять в бизнес процессе, который по вашему расписанию будет отсылать Email сообщение (пример).

А вот сформировать тело сообщения с таблицей без программирования уже сложно.

Добрый день!

Выполнять в бизнес процессе, который по вашему расписанию будет отсылать Email сообщение (пример).

А вот сформировать тело сообщения с таблицей без программирования уже сложно.

Сидоров Александр В.,

Спасибо. Сложно= невозможно, я правильно понимаю ? А если исключить таблицу, и представить просто список ?

LilyG,

Ну да. Считать список можно стандартными блоками БП. А вот из списка сформировать текст, который потом пойдет в сообщение - уже нужен блок "Задание сценарий", а это уже программирование

Показать все комментарии
7.13_()
sales_enterprise

Добрый день!

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

actionMenuItems.addItem(this.getButtonMenuItem({

                    "Caption": {"bindTo": "Resources.Strings.EditRightsCaption"},

                    "Tag": "editRights",

                    "Visible": {"bindTo": "getSchemaAdministratedByRecords"}

                }));

метод же найти не могу.

Нужно для назначения прав на страницу контрагента в БП без использования Terrasoft.Core.DB

Нравится

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

По нажатию на кнопку действия 'Настроить права доступа' вызывается окно для редактирования прав, в котором пользователь вручную раздает права доступа, и его вызов реализован в методе editRights (указан в свойстве 'Tag').

В БП в элементе 'Задание-сценарий' можно реализовать произвольный запрос, в котором выполнять добавление/изменение/удаление данных напрямую в базу данных без использования Terrasoft.Core.DB:

var customQuery = new CustomQuery(context.UserConnection);
customQuery.SqlText = @"insert into Cases (Id) values (newid())";
using (DBExecutor dbExecutor = context.UserConnection.EnsureDBConnection())
{
	var datareader = customQuery.ExecuteReader(dbExecutor);
}
return true;

Вот ещё другой пример:

var userConnection = context.UserConnection;
var dr = new CustomQuery(userConnection, String.Format(
"update case set SolutionProvidedOn = null where Id = 974ca9fc-c066-4a7a-ac65-7ec91a44a067")).ExecuteReader(dbExecutor);
return true;

 

По нажатию на кнопку действия 'Настроить права доступа' вызывается окно для редактирования прав, в котором пользователь вручную раздает права доступа, и его вызов реализован в методе editRights (указан в свойстве 'Tag').

В БП в элементе 'Задание-сценарий' можно реализовать произвольный запрос, в котором выполнять добавление/изменение/удаление данных напрямую в базу данных без использования Terrasoft.Core.DB:

var customQuery = new CustomQuery(context.UserConnection);
customQuery.SqlText = @"insert into Cases (Id) values (newid())";
using (DBExecutor dbExecutor = context.UserConnection.EnsureDBConnection())
{
	var datareader = customQuery.ExecuteReader(dbExecutor);
}
return true;

Вот ещё другой пример:

var userConnection = context.UserConnection;
var dr = new CustomQuery(userConnection, String.Format(
"update case set SolutionProvidedOn = null where Id = 974ca9fc-c066-4a7a-ac65-7ec91a44a067")).ExecuteReader(dbExecutor);
return true;

 

Спасибо, Алла.

В БП этот код вызывает ошибку компиляции "The name dbExecutor does not exist in the current context"

Либо "The type or namespace name 'IDataReader' coul not be found" в первом варианте.

То есть это работает только для неинтерпетируемого процесса? 

Естественно, использование в БП блоков скриптов на C# требует компиляции процесса.

Виталий Егоров,

Если Вы используете второй вариант, попробуйте вместо UserConnection написать context.UserConnection.

 

Если первый вариант, то приблизительно такой код:

var userConnection = context.UserConnection;
var customQuery = new CustomQuery(userConnection);
customQuery.SqlText = @"insert into Cases (Id) values (newid())"; 
using (DBExecutor dbExecutor = userConnection.EnsureDBConnection())
{
	var reader = customQuery.ExecuteReader(dbExecutor);
}
return true;

 

Виталий Егоров пишет:

В БП этот код вызывает ошибку компиляции "The name dbExecutor does not exist in the current context"

Нужно обернуть в using, как и в первом фрагменте. 

 Либо "The type or namespace name 'IDataReader' coul not be found" в первом варианте.

А тут нужно включить нужную библиотеку System.Data в Usings (в дизайнере БП справа на вкладке «Методы»).

Спасибо, Алла, все работает.

Александр, спасибо, попробую добавить DataReader.

Добавил в этот же БП еще один сценарий с кодом:

foreach (string accountId in accountIdList){

    try {

        var update = new Update(UserConnection, "Account")

               .Set("OwnerId", Column.Parameter(newOwner))

               .Where ("Id").IsEqual(Column.Parameter(accountId));

        update.Execute();

    }

    catch (SqlException ex){

        errorsList.Add(ex.Message);

    }

    finally {

        var sel = new Select(UserConnection)

            .Column("Name")

            .From("Account")

            .Where ("Id").IsEqual(Column.Parameter(accountId));

             using (DBExecutor dbExecutor = context.UserConnection.EnsureDBConnection()) {

            using (IDataReader dataReader = sel.ExecuteReader(dbExecutor)){

                       accountName = CreateJson(dataReader);

            }

        }

        accountNameList.Add(accountName);

    }

}

На выходе получаю ошибку:

'Query' does not contain a definition for 'ExecuteReader' and no extension method 'ExecuteReader' accepting a first argument of type 'Query' could be found (are you missing a using directive or an assembly reference?)

 

 

Может, дело в забытом «as Select» в конце объявления sel? Как тут:

Select select = 
	new Select(UserConnection)
		.Column("Id")
		.From("ActivityStatus")
		.Where("Finish").IsEqual(Column.Parameter(true))
		as Select;
using (var dbExecutor = UserConnection.EnsureDBConnection()) {
	using (IDataReader dr = select.ExecuteReader(dbExecutor)) {
		while (dr.Read()) {
			finishActivityStatuses.Add(UserConnection.DBTypeConverter.DBValueToGuid(dr[0]));
		}
	}
}

 

Спасибо, добрый человек! :)

Показать все комментарии
Мобильное приложение
сообщения
Первичный запуск
синхронизация
7.14_()
sales_enterprise

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

Нравится

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

Для вывода сообщения используется функция:

Terrasoft.MessageBox.Show({message:'текст',title:'заголовок'})

 

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

Это понятно как выводить сообщения. Интересует вывод после завершения синхронизации данных.

Определить, загружались ли вообще по синхронизации данные, можно посредством:

!Ext.isEmpty(Terrasoft.CurrentUserInfo.lastSyncDate)

А первый или не первый раз, самому где-то хранить значение-флажок.

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

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

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

"Status": {
		"enabledStatusByUser": {
			"ruleType": BusinessRuleModule.enums.RuleType.BINDPARAMETER,
			"property": BusinessRuleModule.enums.Property.ENABLED,
			"logical": Terrasoft.LogicalOperatorType.AND,
			"conditions": [
				{
					"comparisonType": Terrasoft.ComparisonType.EQUAL,
					"leftExpression": {
						"type": BusinessRuleModule.enums.ValueType.SYSVALUE,
						"attribute": "CURRENT_USER"
					},
					"rightExpression": {
						"type": BusinessRuleModule.enums.ValueType.CONSTANT,
						"value": "7f3b869f-34f3-4f20-ab4d-7480a5fdf647"
					}
				}
			]
		}
	}

 

Нравится

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

Добрый день!

Попробуйте такой код в условиях (conditions)

"conditions": [
	{
		"comparisonType": 3,
		"leftExpression": {
			"type": 3,
			"value": "CurrentUser",
			"dataValueType": 10
		},
		"rightExpression": {
			"type": 0,
			"value": "7f3b869f-34f3-4f20-ab4d-7480a5fdf647",
			"dataValueType": 10
		}
	}
]

 

Добрый день!

Попробуйте такой код в условиях (conditions)

"conditions": [
	{
		"comparisonType": 3,
		"leftExpression": {
			"type": 3,
			"value": "CurrentUser",
			"dataValueType": 10
		},
		"rightExpression": {
			"type": 0,
			"value": "7f3b869f-34f3-4f20-ab4d-7480a5fdf647",
			"dataValueType": 10
		}
	}
]

 

Сидоров Александр В.,

Спасибо, работает

Григорий Чех,

Вы имеете ввиду настроить администрирование по колонкам?

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

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

Спасибо за совет, буду иметь ввиду

Показать все комментарии
UserConnection
бизнес-процесс
7.12
sales_enterprise

Коллеги, здравствуйте!

Подскажите, где происходит сакральный Set("UserConnection", UserConnection) для БП?

Из академического интереса спрашиваю по результатам обсуждения  этого вопроса.

 

Нравится

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

Где то внутри Terrasoft.Core.ProcessEngine.... без исходников или дизасма и не видно :)

Где то внутри Terrasoft.Core.ProcessEngine.... без исходников или дизасма и не видно :)

При запуске процесса из конфигурации, интерпретируемого или компилируемого, UserConnection передаётся извне, как видно из примеров, которые приводил Григорий.

А при запуске через ProcessEngineService там в начале функции ExecuteProcess считывается то самое HttpContext.Current.Session["UserConnection"].

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

Приветствую, коллеги!

Запускается макрос по такой схеме:

  1. БП по таймеру
  2. Подпроцесс
  3. ScriptTask
  4. ReportService
  5. GenerateMSWordReport
  6. Макрос : IExpressionConverter

В макросе надо esq запрос выполнить, пытаюсь получить UserConnection:

 

  • HttpContext.Current.Session["UserConnection"] не работает ибо HttpContext.Current == null
  • Get("UserConnection") - нет метода Get
  • context.UserConnection - нет context в объявленных
  • UserConnection - не переменная, а тип

Как же все таки исхитриццо с UserConnection для esq? можно без него запрос сделать?

 

Нравится

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

См. последний ответ тут.

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

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

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

а теперь до пункта 7 добирается и в методе Evaluate на строке с получением UserConnection ломает процесс

Как вариант, использовать SystemUserConnection.

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

Теперь надо создать топик "Как получить SystemUserConnection в макросе?"

Попробуйте (HttpContext.Current.Application["AppConnection"] as AppConnection).SystemUserConnection.

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

не работает, ибо 

HttpContext.Current равно null

в каком месте можно глянуть, как инициализируется UserConnection, который берется из Get<UserConnection>(“UserConnection”) или context.UserConnecrion для БП?

В примере макроса вообще есть получение UserConnection и HttpContext.Current там не null:

_userConnection = (UserConnection)HttpContext.Current.Session["UserConnection"];

 

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

ну я же схему объяснил, печатная форма делается в БП, запускаемом по таймеру

A HttpContext.Current.Session[“UserConnection”] работает только при запуске через сервис

Если иначе никак, можно работать через OData, как во стороннем приложении.

Капец как сложно, мне всего то надо если ИПешник, ИНН без КПП выводить и запятой лишней не было :)

Формируйте нужный текст в каком-то поле контакта или контрагента, затем выводите в отчёте стандартными средствами, безо всяких макросов.

Решил - переписал:

1) ExpressionConverterHelper, что бы конструктор принимал параметр типа  UserConnection и присваивал его аналогичного типа свойству и в методе GetValue

var expressionConverter = (IExpressionConverter)Activator.CreateInstance(expressionConverterClass);
if (expressionConverter != null) {
    macrosValue.Data = expressionConverter.Evaluate(value, macrosElement.Argument);
}

поменял на

dynamic expressionConverter = Activator.CreateInstance(expressionConverterClass);
if (expressionConverter != null) {
	PropertyInfo propertyInfo = expressionConverter.GetType().GetProperty("UserConnection");
	if (propertyInfo != null) {
		propertyInfo.SetValue(expressionConverter, UserConnection, null);
	}
	macrosValue.Data = expressionConverter.Evaluate(value, macrosElement.Argument);
}

2) в классе ReportService меняем строку

var expressionConverterHelper = new ExpressionConverterHelper();

на 

var expressionConverterHelper = new ZLExpressionConverterHelper(UserConnection);

3) в макросе в начале пишем:

private UserConnection _userConnection;
public UserConnection UserConnection {
    get {
	    if (_userConnection == null) {
		    _userConnection = (UserConnection)HttpContext.Current?.Session["UserConnection"];
	    };
	    return _userConnection;
	}
    set =&gt; _userConnection = value;
}

потом пользуем UserConnection

 

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

Доброго времени суток! Возникла задача реализовать фильтр для детали, одно из условий - чтоб длина номера телефона превышала 4 символа. Возможно ли это реализовать?Если да то как?

Нравится

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

Добрый день!

Посмотрите тут

Сидоров Александр В.,

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

 

На esq реализовать это довольно сложно. Предлагаю сделать представление (view) и фильтровать уже на уровне представления

Либо сделать в объекте ещё одно числовое поле и при добавлении/изменении номера в БП/встроенном БП/триггере вычислять и записывать туда его длину.

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

Благодарю ваш вариант и использовали.

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

Столкнулась со странным поведением системы. Версия 7.14.0.597.

В системной настройке 'CurrentPackageId' указан пользовательский пакет (не Custom), а в настройке 'CustomPackageId' указан пакет Custom.

При редактировании карточки раздела изменения вносятся в нового наследника этой карточки в пакет Custom, причем не под тем пользователем, под которым выполняются изменения, а под пользователем Supervisor (в полях 'Создал' и 'Изменил' нового сервиса указан Supervisor).

Никакие 'танцы с бубнами' не помогают решить данную проблему.

Может кто-то сталкивался с таким или у Вас есть идеи, как можно решить эту проблему?

Возможно, проблемы в параметрах пакета, который указан в 'CurrentPackageId'?

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

Нравится

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

Алла, см. аналогичные вопросы. Судя по отсутствию продолжения тем, должны помочь именно стандартные действия по чистке. Если нет, нужно подключаться и производить отладку.

Показать все комментарии
7.13_()
sales_enterprise

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

Нравится

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