Здравствуйте.
Создал объект на основе базового объекта. Добавил событие "После добавления записи", в нем пул и дорожку.
На дорожку поместил событие "Сообщение".Поведение.Сообщение = "BaseEntityInserted". Вообщем делал по аналогии с базовым объектом, но после сохранение записи БП не выполняется. Что я сделал не так?

Нравится

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

Здравствуйте!
После добавления записи рекомендуется использовать обычные процессы. Вы можете построить бизнес процесс, используя дизайнер процессов. Начальный элемент - сигнал. Настройки сигнала: объект - созданный Вами объект, событие - после добавления записи. Подробнее о бизнес процессах Вы можете прочитать здесь.

Да можно и так, но если я захочу добавить функционал не "После добавления записи", а перед сохранением, тут уже БП не поможет, что в таких случаях нужно делать?

В таких случаях:
1) Добавьте обработку события до "Сохранения записи"
2) Откройте диаграмму процесса
3) Добавьте элемент "Задание-сценарий" (этих элементов может быть несколько, они могут выполняться как последовательно, так и параллельно)
4) Пропишите все, что должно произойти в элементе "Задание-сценарий"

Вся исполняемая логика должна быть в элементе "Задание-сценарий".

"Дашкевич К." написал:

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

Создал объект на основе базового объекта. Добавил событие "После добавления записи", в нем пул и дорожку.

На дорожку поместил событие "Сообщение".Поведение.Сообщение = "BaseEntityInserted". Вообщем делал по аналогии с базовым объектом, но после сохранение записи БП не выполняется. Что я сделал не так?

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

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

Добрый день!
в ITIL
есть такая функция в скрипте CasePage(SLM), которая фильтрует выпадающие списки
ответственных и групп ответственных в обращении.

getOwnerDependenceFilters: function(scope) {
var filterGroup = new scope.Terrasoft.createFilterGroup();
var serviceItem = scope.get("ServiceItem");
var supportLevel = scope.get("SupportLevel");

if (serviceItem) {
filterGroup.add("ServiceItemFilter", scope.Terrasoft.createColumnFilterWithParameter(
scope.Terrasoft.ComparisonType.EQUAL, "[ServiceEngineer:Engineer].ServiceItem", serviceItem.value));
}

return filterGroup;
},

Хотела бы добавить дополнительный фильтр в эту функцию,
для этого мне необходимо получить еще одно поле - по которому фильтровать,
но не просто поле из карточки обращения, а, например, связанное поле, например, статус сервисного договора, указанного в карточке обращения
и вот, если написать
var servicePact = scope.get("servicePact"), то это значение возвращается и определяется
а вот связанная колонка, например:
var status = scope.get("servicePact.Status") возвращается как undefined

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

Нравится

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

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

selectStatusServicePact: function() {
var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
rootSchemaName: "ServicePact"
});
var servicePact = scope.get("servicePact")
esq.addColumn("Id");
esq.addColumn("Status");
esq.filters.add("ServicePactId", this.Terrasoft.createColumnFilterWithParameter(
this.Terrasoft.ComparisonType.EQUAL, "Id", servicePact));
esq.getEntityCollection(function(response) {
if (response && response.success) {
if (response.collection.getCount() > 0) {
var result = response.collection.getItems()[0];
var statusId = result.get("Status");
//или
this.set("StatusServicePact", result.values.Status);
}
}
}

Более подробно ознакомиться с использованием EntitySchemaQuery на клиенте можно здесь

Спасибо, как раз нашла подобный пример в скриптах.
Только в фильтрации надо указывать не servicePact, а servicePact.value

Мой вопрос в следующем- как собственно вывести значение statusid в основную функцию selectStatusServicePact

часть вашего приведенного кода
sq.getEntityCollection(function(response) {
if (response && response.success) {
if (response.collection.getCount() > 0) {
var result = response.collection.getItems()[0];
var statusId = result.get("Status");
}
}
}, this)
переменная statusid доступна только внутри функции sq.getEntityCollection(function(response)
как сделать так, чтобы она(ее значение) была доступна в теле основной функции selectStatusServicePact: function() ?
Мне необходимо получить, допустим, статус договора, и не заполнять им какое-то поле внутри вспомогательной функции, а просто получить это значение, и дальше с ним работать в теле основной функции selectStatusServicePact: function()

Если модифицировать код функции selectStatusServicePact следующим образом, то статус договора будет доступен через this.get("StatusServicePact")

selectStatusServicePact: function(scope) {
var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
rootSchemaName: "ServicePact"
});
var servicePact = scope.get("servicePact")
esq.addColumn("Id");
esq.addColumn("Status");
esq.filters.add("ServicePactId", this.Terrasoft.createColumnFilterWithParameter(
this.Terrasoft.ComparisonType.EQUAL, "Id", servicePact.value));
esq.getEntityCollection(function(response) {
if (response && response.success) {
if (response.collection.getCount() > 0) {
var result = response.collection.getItems()[0];
var statusId = result.get("Status");
//или
scope.set("StatusServicePact", result.values.Status);
}
}
}

Более надежный способ добавить в секцию attributes виртуальную колонку

"StatusServicePact": {
					"dataValueType": Terrasoft.DataValueType.CUSTOM_OBJECT,
					"type": Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
					"value": null
				},

и внутри getEntityCollection сделать this.set("StatusServicePact", result.values.Status);
Далее в теле основной функции используйте this.get("StatusServicePact") для получения статуса договора.

Добавила виртуальную колонку.
Внутри getEntityCollection сделала this.set("StatusServicePact", result.values.Status);
Далее в теле основной функции использовала
var usrNeedTerritory = this.get("StatusServicePact");
- но объект (проверила в дебаггере) возвращается как null (хотя я его заполнила во вспомогательной функции)

Выяснила, чтобы эта схема работала, во вспомогательной функции нужно писать
не
this.set("StatusServicePact", result.values.Status);
а
this.set("StatusServicePact", result.get("Status"));

хотя нет - в и этом случае, похоже, что не работает.
возвращает null this.get("StatusServicePact")

причем, очень странно ведет себя - сначала возвращает null,
ошибка Cannot read property 'value' of null
нажимаю f12,закрываю f12 - и объект уже не null
что-то не так с выводом значения из функции во вне
И так каждый раз при открытии карточки и вызове этого метода в ней
( а именно, при нажатии на кнопку "вниз" в поле "группа ответственных" в карточке обращения)
Объект this.get("StatusServicePact") во внешней функции становится не null, только если включить и отключить f12 (каждый раз, когда открываешь карточку)

"Татаровская Дарья" написал:
И так каждый раз при открытии карточки и вызове этого метода в ней

( а именно, при нажатии на кнопку "вниз" в поле "группа ответственных" в карточке обращения)

Объект this.get("StatusServicePact") во внешней функции становится не null, только если включить и отключить f12 (каждый раз, когда открываешь карточку)

Привидите весь код страницы, по куску кода трудно предположить что происходит

В аттрибутах добавлена виртуальная колонка

attributes: {
"TerritoryServicePact": {
"dataValueType": Terrasoft.DataValueType.CUSTOM_OBJECT,
"type": Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
"value": null
},

функция
getOwnerDependenceFilters: function(scope) {
//debugger;
var filterGroup = new scope.Terrasoft.createFilterGroup();
var serviceItem = scope.get("ServiceItem");
var servicePact = scope.get("ServicePact");
//var usrTerritory;
if (servicePact) {

var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
rootSchemaName: "ServicePact"
});
esq.addColumn("Id");
esq.addColumn("UsrTerritory");
//esq.addColumn("Status");
esq.filters.add("ServicePactId", this.Terrasoft.createColumnFilterWithParameter(
this.Terrasoft.ComparisonType.EQUAL, "Id", servicePact.value));
esq.getEntityCollection(function(response) {
if (response && response.success) {
if (response.collection.getCount() > 0) {
var result = response.collection.getItems()[0];
this.set("TerritoryServicePact",result.get("UsrTerritory"));
//scope.set("MyStatus",result.get("MyStatus"));
}
}
}, this);
}
var usrNeedTerritory = this.get("TerritoryServicePact");
var usrNeedTerritoryvalue = usrNeedTerritory.value;

if (serviceItem) {
filterGroup.add("ServiceItemFilter", scope.Terrasoft.createColumnFilterWithParameter(
scope.Terrasoft.ComparisonType.EQUAL, "[ServiceEngineer:Engineer].ServiceItem", serviceItem.value));
}
if ((servicePact) ) {
filterGroup.add("TerritoryItemFilter", scope.Terrasoft.createColumnFilterWithParameter(
scope.Terrasoft.ComparisonType.EQUAL, "[ServiceEngineer:Engineer].UsrNeedTerritory", usrNeedTerritoryvalue));
}
return filterGroup;
}

В этом
примере выбирается новая колонка,добавленная в договор ( но такая ситуация повторяется, если выбирать любую колонку из договора)
var usrNeedTerritory = this.get("TerritoryServicePact") - этот объект(переданный из вспомогательной функции в основную) становится не null, только со второй попытке при открытии карточки, причем только после нажатия и отжатия кнопки f12

Татьяна вы можете привести весь код страницы полностью?
Из кусочка кода что вы привели я не вижу как и когда вызывается getOwnerDependenceFilters, какие модули подключены в вашу страницу и тд.

да, конечно

define("CasePage", ["CasePageResources", "GeneralDetails", "BusinessRuleModule"],
function(resources, GeneralDetails, BusinessRuleModule) {
return {
entitySchemaName: "Case",
details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
diff: /**SCHEMA_DIFF*/[
]/**SCHEMA_DIFF*/,
attributes: {
"TerritoryServicePact": {
"dataValueType": Terrasoft.DataValueType.CUSTOM_OBJECT,
"type": Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
"value": null
}
},
methods: {
getOwnerDependenceFilters: function(scope) {
//debugger;
var filterGroup = new scope.Terrasoft.createFilterGroup();
var serviceItem = scope.get("ServiceItem");
var servicePact = scope.get("ServicePact");
//var usrTerritory;
if (servicePact) {
var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
rootSchemaName: "ServicePact"
});
esq.addColumn("Id");
esq.addColumn("UsrTerritory");
//esq.addColumn("Status");
esq.filters.add("ServicePactId", this.Terrasoft.createColumnFilterWithParameter(
this.Terrasoft.ComparisonType.EQUAL, "Id", servicePact.value));
esq.getEntityCollection(function(response) {
if (response && response.success) {
if (response.collection.getCount() > 0) {
var result = response.collection.getItems()[0];
this.set("TerritoryServicePact",result.get("UsrTerritory"));
//scope.set("MyStatus",result.get("MyStatus"));
}
}
}, this);
}
var usrNeedTerritory = this.get("TerritoryServicePact");
var usrNeedTerritoryvalue = usrNeedTerritory.value;

if (serviceItem) {
filterGroup.add("ServiceItemFilter", scope.Terrasoft.createColumnFilterWithParameter(
scope.Terrasoft.ComparisonType.EQUAL, "[ServiceEngineer:Engineer].ServiceItem", serviceItem.value));
}
if ((servicePact) ) {
filterGroup.add("TerritoryItemFilter", scope.Terrasoft.createColumnFilterWithParameter(
scope.Terrasoft.ComparisonType.EQUAL, "[ServiceEngineer:Engineer].UsrNeedTerritory", usrNeedTerritoryvalue));
}
return filterGroup;
},
onEntityInitialized: function() {
if (this.isAddMode() || this.isCopyMode()) {
this.setCaseNumber();
}
this.Terrasoft.SysSettings.querySysSettingsItem(this.statusDefSysSettingsName, function(value) {
this.set("StatusDefSysSettingsValue", value);
}, this);
this.updateOriginals();
var contact = this.get("Contact");
if (contact && !this.get("Account")) {
var account = contact.Account;
if (account) {
this.set("Account", account);
}
}
this.set("Owner", Terrasoft.SysValue.CURRENT_USER_CONTACT);
this.callParent(arguments);
}
},
rules: {
},
userCode: {}
};
});

getOwnerDependenceFilters - вызывается в сервисе стандартном CasePage (пакет SLMItilService, Case) - вызов этой функции там же и описан
в своей же схеме(унаследованной) я хочу переопределить саму функцию getOwnerDependenceFilters

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

define("CasePage", ["CasePageResources", "GeneralDetails", "BusinessRuleModule", "BaseFiltersGenerateModule", "terrasoft"],
function(resources, GeneralDetails, BusinessRuleModule, BaseFiltersGenerateModule, Terrasoft) {
return {
    entitySchemaName: "Case",
    details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
    diff: /**SCHEMA_DIFF*/[ ]/**SCHEMA_DIFF*/,
    attributes: {
        "TerritoryServicePact": {
            "dataValueType": Terrasoft.DataValueType.CUSTOM_OBJECT,
            "type": Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
            "value": null
        },
        "TerritoryServicePact2": {
            "dataValueType": Terrasoft.DataValueType.CUSTOM_OBJECT,
            "type": Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
            "value": null
        },
        "Owner": {
            dataValueType: Terrasoft.DataValueType.LOOKUP,
            lookupListConfig: {
                filter: function () {
                    return this.getOwnerDependenceFilters();
                }
            }
        }
    },
    methods: {
        getOwnerDependenceFilters: function () {
            //debugger;
            var filterGroup = new this.Terrasoft.createFilterGroup();
            var serviceItem = this.get("ServiceItem");
            var servicePact = this.get("ServicePact");
            //если договор выбран на карточке редактирования иначе undef;
            if (servicePact) {
                var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
                    rootSchemaName: "ServicePact"
                });
                esq.addColumn("Id");
                esq.addColumn("Status.Id", "StatusId");
                esq.addColumn("Status.Name", "StatusName");
                //esq.addColumn("Status.Id","");
                esq.filters.add("ServicePactId", this.Terrasoft.createColumnFilterWithParameter(
                    this.Terrasoft.ComparisonType.EQUAL, "Id", servicePact.value));
                esq.getEntityCollection(function (response) {
                    if (response && response.success) {
                        if (response.collection.getCount() > 0) {
                            var result = response.collection.getItems()[0];
                            this.set("TerritoryServicePact", result.get("StatusId"));
                            this.set("TerritoryServicePact2", result.get("StatusName"));
                            console.log(result.get("StatusId"));
                        }
                    }
                }, this);
            }
            var usrNeedTerritory = this.get("TerritoryServicePact");
            //выдаю сообщение для отладки с названием статуса
            this.showInformationDialog(this.get("TerritoryServicePact2"));
            var usrNeedTerritoryvalue = usrNeedTerritory;
 
            if (serviceItem) {
                filterGroup.add("ServiceItemFilter", scope.Terrasoft.createColumnFilterWithParameter(
                    scope.Terrasoft.ComparisonType.EQUAL, "[ServiceEngineer:Engineer].ServiceItem", serviceItem.value));
            }
            if (servicePact) {
                filterGroup.add("TerritoryItemFilter", scope.Terrasoft.createColumnFilterWithParameter(
                    scope.Terrasoft.ComparisonType.EQUAL, "[ServiceEngineer:Engineer].UsrNeedTerritory", usrNeedTerritoryvalue));
            }
            return filterGroup;
        },
        onEntityInitialized: function() {
            if (this.isAddMode() || this.isCopyMode()) {
                this.setCaseNumber();
            }
            this.Terrasoft.SysSettings.querySysSettingsItem(this.statusDefSysSettingsName, function(value) {
            this.set("StatusDefSysSettingsValue", value);
            }, this);
            this.updateOriginals();
            var contact = this.get("Contact");
            if (contact && !this.get("Account")) {
                var account = contact.Account;
                if (account) {
                    this.set("Account", account);
                }
            }
            this.set("Owner", Terrasoft.SysValue.CURRENT_USER_CONTACT);
            this.callParent(arguments);
        }
    },
    rules: {},
    userCode: {}
};
});;

Дело не вызове функции, функция вызывается.
Насколько я поняла, вы в примере предложили дописать вызов функции, и это фильтр на выбор из справочника, но это не тот случай.
Функция getOwnerDependenceFilters вызывается в родительской схеме, как я уже писала, в моей же дочерней схеме она просто переопределяется.
Причем фильтр работает не на выбор из справочника, а на нажатие кнопки "вниз".
Вызов функции getOwnerDependenceFilters происходит - это точно.
Она вызывается -я в нее и дебаггером попадаю - и она отрабатывает вся целиком.
Вызов этой функции происходит в родительской схеме:
( а именно, CasePage(пакет Case) -здесь происходит вызов функции, и ее определение
далее, унаследованная CasePage(пакет SLMItilService) - здесь происходит переопределение функции
далее, унаследованная моя страничка - в которой я еще раз переопределяю функцию.

Функция эта переопределенная сама по себе работает корректно.
Но почему-то если добавить в мою переопределенную функцию вот такую подфункцию для вытаскивания значения связанного поля,
то значение это, как я уже говорила, становится не пусто только во второй раз.
Есть,допустим, поле "группа ответственных" (или ответственный), я нажимаю на кнопку вниз,
и в этот момент срабатывает функция фильтрации getOwnerDependenceFilters
вывожу сообщение для отладки this.showInformationDialog(this.get("TerritoryServicePact"));
и оно пусто
Еще раз нажимаю на кнопку вниз, опять срабатывает функция фильтрации getOwnerDependenceFilters,
вывожу сообщение для отладки this.showInformationDialog(this.get("TerritoryServicePact")),
и оно уже не пусто!
То есть наблюдается какая-то очень странная передача параметра из вспомогательной подфункции в основную - только со второго раза.

Предположила, что может дело в том, что фильтр вызывается на нажатие кнопки "вниз" - но нет, та же ситуация повторяется, если применять фильтр на выбор из справочника.

Предположила, что может быть так происходит, только если замещать функцию - но нет, т.к.
проверила ваш пример - если создать функцию не унаследованную - getOwnerDependenceFilters1, например, и вызвать ее для аттрибута Owner - то точно такая же ситуация повторяется в вашем примере..

Дарья getEntityCollection выполняет получение результата запроса асинхронно, а выполнение в функции getOwnerDependenceFilters идет дальше, не дожидаясь получения результата работы запроса.
При следующем клике значение из колонки берется то что было получено в первом запросе.
Я сделал виртуальную колонку TerritoryServicePact зависимой от изменения поля ServicePact (при изменении поля вызывается метод calculateStatus в котором выполняется запрос к БД и определяется статус договора), таким образом при вызове фильтра если был выбран сервисный договор, то у нас уже в TerritoryServicePact будет статус текущего договора.

define("CasePage", ["CasePageResources", "GeneralDetails", "BusinessRuleModule", "BaseFiltersGenerateModule", "terrasoft"],
function(resources, GeneralDetails, BusinessRuleModule, BaseFiltersGenerateModule, Terrasoft) {
return {
    entitySchemaName: "Case",
    details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
    diff: /**SCHEMA_DIFF*/[ ]/**SCHEMA_DIFF*/,
    attributes: {
        "TerritoryServicePact": {
            "dataValueType": Terrasoft.DataValueType.CUSTOM_OBJECT,
            "type": Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
            "value": null,
            dependencies: [
                {
                    // Значение колонки [TerritoryServicePact] зависит от значений колонок [ServicePact]
                    columns: ["ServicePact"],
                    // Метод-обработчик, который вызывается при изменении значения [ServicePact]
                    methodName: "calculateStatus"
                }
            ]
        },
        "TerritoryServicePact2": {
            "dataValueType": Terrasoft.DataValueType.CUSTOM_OBJECT,
            "type": Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
            "value": null
        },
        "Owner": {
            dataValueType: Terrasoft.DataValueType.LOOKUP,
            lookupListConfig: {
                filter: function () {
                    return this.getOwnerDependenceFilters();
                }
            }
        }
    },
    methods: {
        // Метод-обработчик, который рассчитывает значение колонки [TerritoryServicePact].
        calculateStatus: function () {
            var servicePact = this.get("ServicePact");
            //если договор выбран на карточке редактирования иначе undef;
            if (servicePact) {
                var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
                    rootSchemaName: "ServicePact"
                });
                esq.addColumn("Id");
                esq.addColumn("Status.Id", "StatusId");
                esq.addColumn("Status.Name", "StatusName");
                //esq.addColumn("Status.Id","");
                esq.filters.add("ServicePactId", this.Terrasoft.createColumnFilterWithParameter(
                    this.Terrasoft.ComparisonType.EQUAL, "Id", servicePact.value));
                esq.getEntityCollection(function (response) {
                    if (response && response.success) {
                        if (!response.collection.isEmpty()) {
                            var result = response.collection.getItems()[0];
                            this.set("TerritoryServicePact", result.get("StatusId"));
                            this.set("TerritoryServicePact2", result.get("StatusName"));
                            console.log("rez="+result.get("StatusId"));
                        }
                    }
                }, this);
            }
        },
        getOwnerDependenceFilters: function () {
            //debugger;
            var filterGroup = new this.Terrasoft.createFilterGroup();
            var serviceItem = this.get("ServiceItem");
            var servicePact = this.get("ServicePact");
            //если договор выбран на карточке редактирования иначе undef;
            if (servicePact) {
                var usrNeedTerritory = this.get("TerritoryServicePact");
                //выдаю сообщение для отладки с названием статуса
                this.showInformationDialog(this.get("TerritoryServicePact2"));
                var usrNeedTerritoryvalue = usrNeedTerritory;
                filterGroup.add("TerritoryItemFilter", this.Terrasoft.createColumnFilterWithParameter(
                    this.Terrasoft.ComparisonType.EQUAL, "[ServiceEngineer:Engineer].UsrNeedTerritory", usrNeedTerritoryvalue));
            }
            if (serviceItem) {
                filterGroup.add("ServiceItemFilter", this.Terrasoft.createColumnFilterWithParameter(
                    this.Terrasoft.ComparisonType.EQUAL, "[ServiceEngineer:Engineer].ServiceItem", serviceItem.value));
            }
            return filterGroup;
        },
        onEntityInitialized: function() {
            if (this.isAddMode() || this.isCopyMode()) {
                this.setCaseNumber();
            }
            this.Terrasoft.SysSettings.querySysSettingsItem(this.statusDefSysSettingsName, function(value) {
            this.set("StatusDefSysSettingsValue", value);
            }, this);
            this.updateOriginals();
            var contact = this.get("Contact");
            if (contact && !this.get("Account")) {
                var account = contact.Account;
                if (account) {
                    this.set("Account", account);
                }
            }
            this.set("Owner", Terrasoft.SysValue.CURRENT_USER_CONTACT);
            this.callParent(arguments);
        }
    },
    rules: {},
    userCode: {}
};
});;

Спасибо, теперь понятно, откуда такое поведение - из-за того, что
etEntityCollection выполняет получение результата запроса асинхронно.

Но не понятно до конца по-прежнему получение значения связанной колонки в карточке.
Вы сделали виртуальную колонку TerritoryServicePact зависимой от изменения поля ServicePact (при изменении поля вызывается метод метод calculateStatus в котором выполняется запрос к БД и определяется статус договора)

Но метод-то этот вызывается только при изменении поля ServicePact, тогда при вызове фильтра в поле "ответственный" в карточке все ок
А если я просто открываю карточку на редактирование( уже готовую), в ней уже выбран договор, это поле не меняется, и метод calculateStatus естественно не вызывается, и фильтр вообще тогда не работает.
Надо еще в каком-то месте вызывать получается метод?

Дарья просто вызовите метод calculateStatus при инициализации страницы CasePage :smile:

спасибо

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

Добрый день!

При создании страниц редактирования для раздела (например, в Контрагентах) в Мастере раздела, созданные страницы наследуются от BaseModulePageV2 ( NUI ).
И тогда приходится дублировать всю имеющуюся функциональность.

Можно ли поменять родительский объект на AccountPageV2 ( UIv2 )? Тогда остается лишь проделать небольшие модификации, оставляя стандартные поля, детали и клиентскую логику.

Какие подводные камни можно ожидать при таком подходе?

Нравится

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

Здравствуйте!
Вы можете изменить родительский объект на другой, тогда у страниц редактирования реализуется логика нового объекта. Редактировать объект с базового пакета Вы не сможете. Для этого Вам необходимо заместить его. В замещающем объекте Вы сможете задать общую логику для всех страниц редактирования.

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

Здравствуйте. Есть задача запускать процесс по расписанию в ночное время или с определенной периодичностью (включая ночное время), когда пользователи в системе не активны.
Подскажите пожалуйста, как правильно запускать процесс(от фиксированного имени пользователя или текущего) и как настроить пул на iis, чтоб была возможность запускать процессы в любое время?

Планировал процесс следующим образом:

// Задание интервала запуска процесса (в минутах).
        int minutleyInterval = IntervalContentEngine;
        var jobName="sxContentEngineProcessJob";
        var jobGroup="RefreshFromContentEngineProcessGroup";
       
if(!AppScheduler.DoesJobExist(jobName,jobGroup)){

        // Добавление задания по запуску процесса в планировщик.
        AppScheduler.ScheduleMinutelyProcessJob(jobName, jobGroup, "sxContentEngineProcess",
            UserConnection.Workspace.Name, UserConnection.CurrentUser.Name, minutleyInterval);
}

Нравится

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

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

Если у Вас on-demand, то следующий абзац можно упустить.
Для того, чтобы процессы постоянно, а главное вовремя, запускались, должны быть выполнены два условия:
1) Пул приложения должен быть запущен
2) Сайт должен работать

Чтобы выполнялось первое условие, установите таймаут простоя IIS равным 0:

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

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

Алексей, вроде бы получилось, спасибо!
Полностью проверить удастся завтра.
Также, если кому-то пригодится, smarterPing нужно устанавливать через имеющийся bat-файл из командной строки,запущенной от имени администратора.

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

Добрый день, используя элемент Добавление данных в БП необходимо установить "Завершение" на следующий день, собственно вопрос как добавить к текущей дате 1 день или несколько часов?

Нравится

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

Здравствуйте, Олег!

Предлагаю простой способ без использования программирования.
Приблизительная инструкция
1) Создайте параметр бизнес процесса с типом Дата/время.
2) Используйте элемент "Формула". Заполните его следующим образом:
"Установить параметр в" - параметр, созданный на первом шаге
Параметр:
Выбор значения.Текущее значение даты и времени + Выбор значения.Выбор времени.[Значение времени]

[Значение времени] - отсрочка во времени. Нельзя выбрать больше 23 часов, 45 минут. Для отсрочки в один день Вам придется использовать два слагаемых.
3) Используйте "Добавить данные" для создания активности. Укажите в поле "Завершение" параметр, созданный на первом шаге.

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

Алексей, спасибо, работает вот такая конструкция

[#Системная переменная.Текущее значение даты и времени#] + [#Значение времени.12:00#] + [#Значение времени.12:00#]

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

Здравствуйте.
Подскажите пожалуйста как изменить\переопределить существующий компонент. И как добавить свой.
На данный момент в модуле в котором использую компонент делаю так:

Ext.define("Terrasoft.controls.UsrTextEdit", {
        extend: "Terrasoft.BaseEdit",
        alternateClassName: "Terrasoft.UsrTextEdit",
        left: "",
        top: "",
        combineStyles: function() {
                var styles = this.callParent(arguments);
                var left = this.left ? this.left : "";
                var top = this.top ? this.top : "";
                var wrapStyle = styles.wrapStyle;
                if (left) {
                        wrapStyle.left = left;
                }
                if (top) {
                        wrapStyle.top = top;
                }
                return styles;
        },
        init: function() {
                this.callParent(arguments);
                this.addEvents(
                        "onmousedown",
                        "onmousemove",
                        "onmouseup"
                );
        },
        initDomEvents: function() {
                this.callParent(arguments);
                var el = this.getEl();
                el.on({
                        "onmousedown": {
                                fn: this.onMouseDown,
                                scope: this
                        },
                        "onmousemove": {
                                fn: this.onMouseMove,
                                scope: this
                        },
                        "onmouseup": {
                                fn: this.onMouseUp,
                                scope: this
                        }
                });
        },
        onMouseDown: function(e) {
                Console.Log('onMouseDown');
                this.fireEvent("onmousedown", this, e);
        },
        onMouseMove: function(e) {
                Console.Log('onMouseMove');
                this.fireEvent("onmousemove", this, e);
        },
        onMouseUp: function(e) {
                Console.Log('onMouseUp');
                this.fireEvent("onmouseup", this, e);
        }
});

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

Нравится

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

Добрый день!

Попробуйте убрать приставку "on" из названия событий "onmousedown", "onmousemove", "onmouseup". Фреймворк должен сам определять, нужна она или нет.

Также для вывода в консоль необходимо использовать нижний регистр: console.log(...).

Олег, спасибо. Нужно было без приставки on.

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

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

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

var serviceItem = this.get("ServiceItem");
if (!serviceItem) {
return;
}
var select = this.Ext.create("Terrasoft.EntitySchemaQuery", {
rootSchemaName: "ServiceItem"
});
select.addColumn("Owner.Account");
select.filters.add("ServiceItemIdFilter",
select.createColumnFilterWithParameter(
this.Terrasoft.ComparisonType.EQUAL, "Id", serviceItem.value));
select.getEntityCollection(function(result) {
if (result.success && result.collection.getCount()) {
var entity = result.collection.getByIndex(0);

this.set("UsrColumn", entity.values.Owner.Account);

}
}, this);

Вопрос - как правильно получить здесь значение контрагента ответственного в последней строке?
Такой способ неправильный entity.values.Owner.Account...

Если бы в select получили бы просто select.addColumn("Owner"),
то обратиться можно было бы entity.values.Owner
А как правильно обращаться в случае более сложного селекта select.addColumn("Owner.Account")?
Подскажите, пожалуйста
entity.values.Owner

Нравится

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

Можно добавить колонку в select следующим образом:

select.addColumn("Owner.Account","OwnerAccount");

И затем получить ее по заданному имени:

this.set("UsrColumn", entity.get("OwnerAccount"));

спасибо

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

Здравствуйте!
Где можно найти информацию о свойствах sandbox?

sandbox.publish("UpdateDetail", this.get("Id"), [sandbox.id]);

Например что и куда передается в этой строке. Где хранится UpdateDetail и прочее..

Спасибо большое!

После добавления данного действия в код стала возникать ошибка "Ошибка сохранения: This SqlTransaction has completed; it is no longer usable."

Нравится

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

Добрый день!

"Исаева Сабина" написал:

Где можно найти информацию о свойствах sandbox?

sandbox.publish("UpdateDetail", this.get("Id"), [sandbox.id]);

Общую информацию о свойствах объекта sandbox можно найти здесь:
- http://www.terrasoft.ru/bpmonlinesdk/ (можно воспользоваться поиском)
- http://www.terrasoft.ru/bpmonlinesdk/SubstitutionMechanism.html
- http://www.terrasoft.ru/bpmonlinesdk/ModuleDevelopmentInBPMonline.html

"Исаева Сабина" написал:

Например что и куда передается в этой строке. Где хранится UpdateDetail и прочее..

В данной строке значение this.get("Id") передается в метод, который подписан на сообщение "UpdateDetail" от модуля sandbox.id

UpdateDetail - это название сообщения. Оно может хранится в любом модуле, который подписан на это сообщение.

Пример подписки модуля на сообщение:

  messages: {
                               "UpdateDetail": {
                                               mode: Terrasoft.MessageMode.PTP,
                                               direction: Terrasoft.MessageDirectionType.SUBSCRIBE
                               }
                },
 methods: {
                               init: function() {
                                               this.callParent(arguments);
                                               this.sandbox.subscribe("UpdateDetail", this.onCardUpdateDetail, this, subscribersIds);
                               },
                               onCardUpdateDetail: function(inputArg){
 
                               }
                }

В любом модуле, где реализован данный код, и которая загружена в момент вызова sandbox.publish, выполнится метод onCardUpdateDetail и в него передастся this.get("Id") в переменную inputArg, если sandbox.id содержится в subscribersIds и если публикация и подписка настроена правильно для конкретной версии приложения.

Спасибо.

Буду вам весьма признательна если вы сможете мне помочь с ошибкой.
Я добавила одну ошибочную строчку с sandbox. После компиляции возникли ошибки. "Ошибка сохранения: This SqlTransaction has completed; it is no longer usable." и еще несколько строчек.
После удаления этого кода ошибка не исчезла. Теперь в системе невозможно делать никакие изменения, т.к. выходит эта ошибка.
Можно это как убрать?
Что можно предпринять?

"Исаева Сабина" написал:

Спасибо.

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

Я добавила одну ошибочную строчку с sandbox. После компиляции возникли ошибки. "Ошибка сохранения: This SqlTransaction has completed; it is no longer usable." и еще несколько строчек.

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

Можно это как убрать?

Что можно предпринять?

Сабина, я писал ранее:


выполнится метод onCardUpdateDetail и в него передастся this.get("Id") в переменную inputArg, если sandbox.id содержится в subscribersIds и если публикация и подписка настроена правильно для конкретной версии приложения .

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

Также посмотрите здесь:
https://www.google.com.ua/webhp?sourceid=chrome-instant&ion=1&espv=2&ie…

Вопрос удален..

Сабина, если у Вас остались вопросы, то сообщите нам.

Спасибо, Дмитрий!
Ну вопросов, как говорится, хоть отбавляйте.

sandbox.publish("PushHistoryState", {
hash: "CardModule/ContactPage/view", stateObj: { id: recordId }
});

Здесь, если я правильно понимаю, я передаю Id одной записи.
Как мне передать коллекцию записей(enum, string, array ) ?

Указанный код предусматривает собой открытие одной карточки (записи).
Отображать запись можно только используя один уникальный идентификатор, таким образом невозможно открыть (передавать) несколько записей одновременно.

Ну страничка не ContactPage а произвольная, которая должна принимать коллекцию İd.
(а как подругому можно передать много İd другой странице?)

Для открытия страницы записи передается только один конкретный ID для конкретной карточки.
Пример:

../0/Nui/ViewModule.aspx#SectionModuleV2/OrderSectionV2/OrderPageV2/edit/8838b3bd-80eb-40e1-95c5-c466ea0f6208

Вопрос вне темы.
Вы не знаете где находится код реализации кнопки Добавить(Задачу, Звонок, Эмаил) в разделе активности?? Ну никак не могу найти.

Сабина, кнопка реализована в схеме BaseSectionV2

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

Здраствуйте! Возникла ошибка при залитии изменений на СВН. Существует 3 конфигурации, и если кто-то хочет зафиксировать изменения в хранилище, выдает сообщение "Сервер занят, попробуйте повторить позже" и так постоянно для всех 3 пользователей. Подскажите пожалуйста в чем может быть проблема и как ее решить.

Нравится

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

Здравствуйте, Владимир!

Ошибка появляется только при фиксации изменений в bpm'online или даже если Вы делаете коммит через клиент для контроля версий (например, TortoiseSVN) ?

Ми не використувуємо TortoiseSVN для фіксації змін. Помилка появляється тільки при фіксації змін із bpm'online

Владимир, попробуйте сделать коммит через другой клиент.

Чтобы найти решение, нам важно понять, чего касается эта проблема - настроек bpm'online или же самого SVN.

У нас такая проблема была, когда на CommitLocker'e осталась блокировка последнего закоммитившегося пользователя. С помощью вышеупомянутой тортилы снимаете блокировку, и после этого спокойно фиксируетесь

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

Добрый день!

Подскажите, пожалуйста, вариант решения для автоматической нумерации позиций в документе (нумерация записей в детали карточки).

Есть такой "Базовый объект с позицией", но поддержка сказала его не использовать в 7.х, и надо писать свою логику на клиенте. Может, кто сталкивался?

Спасибо!

Нравится

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

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

Для решения задачи нужно создать колонку (int) (к примеру «Position») на объекте, после этого на клиентском модуле написать функцию подсчета записей и обновления счетчика позиции для записи.

"Вильшанский Дмитрий" написал:

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

Для решения задачи нужно создать колонку (int) (к примеру «Position») на объекте, после этого на клиентском модуле написать функцию подсчета записей и обновления счетчика позиции для записи.

Возникает еще вопрос с удалением и пересчётом позиций. Это уже явно лучше делать на сервере

Мне нравится идея, которая заложена в объекте "Базовый объект с позицией", но есть опасения, что если он не поддерживается далее, то могут быть проблемы

Владимир, Вы можете использовать метод в объекте «Базовый объект с позицией», данное решение будет функционировать без каких либо проблем.
С нашей стороны рекомендуем делать кастомизации на клиентском модуле так как данный подход больше соответствует нынешнему ходу разработки кастомизаций для приложения

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