получение связанного поля на странице редактирования

Добрый день!
в 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:

спасибо

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