Вопрос

работа асинхронной функции

Добрый день!

Есть такой метод

            calcCountRec: function() {

                    var esq = Ext.create("Terrasoft.EntitySchemaQuery", {

                        rootSchemaName: "UsrProductInActivity"

                    });

                    esq.addAggregationSchemaColumn("Id",

                        Terrasoft.AggregationType.COUNT, "UsrProductInActivityCount");

                    esq.filters.addItem(this.Terrasoft.createColumnFilterWithParameter(

                        this.Terrasoft.ComparisonType.EQUAL, "UsrActivity",  this.get("UsrActivity").value));

                    esq.getEntityCollection(function(response) {

                        if (response.success) {

                            var collection = response.collection;

                           if (collection) {

                                this.set("CountRec", collection.getByIndex(0).get("UsrProductInActivityCount"));

                            }

                        }

                    }, this);

                    

                },

 

где CountRec - это виртуальный атрибут

            "CountRec": {

                "type": this.Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,

                "dataValueType": this.Terrasoft.DataValueType.FLOAT

            }

 

 

Необходимо при сохранении записи в методе save написать некие проверки, в которых было бы задействовано значение рассчитанного атрибута CountRec

Подскажите, где и как можно вызвать метод calcCountRec, чтобы значение CountRec не было undefined ? (может быть надо как-то сам метод изменить?)

если в save вызвать, и потом в save проверки - то значение undefined

если в onEntityInitialized вызвать, а потом в save проверки - то значение undefined

 

 

Нравится

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

Можно вообще всё вычислять без арибута прямо в методе сохранения. Или сделать обычное поле и заполнять значением суммы при сохранении записи на детали продуктов при помощи БП или триггера.

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

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

А как можно вычислить без атрибута прямо в методе сохранения?

Так же само, как сейчас вычисляете внутри функции. Но зачем каждый раз вычислять сумму, если можно сделать поле и хранить в нём.

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

Это одно из вычислений(просто пример вычисления)

Есть второе вычисление - в другом методе

                

                calcCurrencyIdFromActivity: function() {

                var activityId = this.get("UsrActivity");

                if (activityId) {

                    var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {

                        rootSchemaName: "Activity"

                    });

                    esq.addColumn("Id");

                    esq.addColumn("UsrCurrency.Id", "CurrencyActivity");

                    esq.filters.add("ActivityId", this.Terrasoft.createColumnFilterWithParameter(

                        this.Terrasoft.ComparisonType.EQUAL, "Id", activityId.value));

                    esq.getEntityCollection(function(response) {

                        if (response && response.success) {

                            if (!response.collection.isEmpty()) {

                                var result = response.collection.getItems()[0];

                                this.set("CurrencyIdActivity", result.get("CurrencyActivity"));

                            }

                        }

                    }, this);

                }

            }

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

типа if this.get("CurrencyIdActivity").value==.. &&  this.get("CountRec").value

Но если вызывать эти функции, а потом посмотреть значения этих атрибутов, то они undefined, соответственно проверку выполнить невозможно.

 

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

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

то есть те же самые 2 метода,вызвать их в методе save, но  внутри методов вместо записи  в виртуальные атрибуты запись в локальную переменную?

то есть вместо, например,

this.set("CountRec", сollection.getByIndex(0).get("UsrProductInActivityCount"));

будет

var cc= сollection.getByIndex(0).get("UsrProductInActivityCount"))

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

Или вы имеете ввиду объединить 2 метода в один как-то?

 

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

 

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

Его не надо записывать в таблицу, подсчет количества был просто в качестве примера. Например, при сохранении карточки "Продукты в активности" нужно вычислить(получить) значение поля Валюта из Активности,  а еще получить значение любого другого связанного поля из другой связанной таблицы(не важно, например, должность контакта).  Вопрос-то же.. не в этом был изначально.. Вопрос был в том как работать с результатом метода...Может быть можно как-то переделать сам метод, чтобы после его выполнения получить значение на выходе, и работать с ним дальше?..

 

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

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

Функция нижеприведенная, к сожалению, не может вернуть ни значения currencyActivity, ни значения sumQuantity, ни значения сс, потому что все эти переменные существуют только  в рамках esq.getEntityCollection(function(response) {...}

calcCheckCurrency: function() {

                var activityId = this.get("UsrActivity");

                if (activityId) {

                    var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {

                        rootSchemaName: "Activity"

                    });

                    esq.addColumn("Id");

                    esq.addColumn("UsrCurrency.Id", "CurrencyActivity");

                    esq.addColumn("UsrSumQuantity","SumQuantity");

                    esq.filters.add("ActivityId", this.Terrasoft.createColumnFilterWithParameter(

                        this.Terrasoft.ComparisonType.EQUAL, "Id", activityId.value));

                    esq.getEntityCollection(function(response) {

                        if (response && response.success) {

                            if (!response.collection.isEmpty()) {

                                var result = response.collection.getItems()[0];

                                var currencyActivity=result.get("CurrencyActivity");

                                var sumQuantity=result.get("SumQuantity");

                                

                                

                                if ((currencyActivity !==this.get("UsrCurrency").value) &&

                                    (

                                    ((this.isAddMode() || this.isCopyMode()) && (sumQuantity>=1))

                                    ||

                                    ((this.isEditMode()) && (sumQuantity>1))

                                    )

                                   )

                                    {

                                        var cc=1;

                                        //this.showInformationDialog("Валюта не совпадает //с ранее выбранной");

                                    }

    

                            }

                        }

                    }, this);

                }

        },

 

                

В таком случае можно всю логику реализовать тоже внутри функции, которая вызывается по завершению getEntityCollection.

Добрый день! Внутри это где? Не поняла вас.

Проблема-то как раз в том, что асинхронно работает, и после завершения getEntityCollection  не доступны данные там вычисленные, они undefined.

Нужно, если условие не выполняется (условие проверяется внутри getEntityCollection), то выводить предупреждение и не сохранять карточку. Если выполняется, то сохранять карточку.

О методе save написан текст вышеприведенный, условие проверяется внутри getEntityCollection, предупреждение выводится - все прекрасно. Но не понятно, как вызвать здесь родительское стандартное сохранение

Если написать так:

                                if ((currencyActivity !==this.get("UsrCurrency").value) &&

                                    (

                                    ((this.isAddMode() || this.isCopyMode()) && (sumQuantity>=1))

                                    ||

                                    ((this.isEditMode()) && (sumQuantity>1))

                                    )

                                   )

                                    {

                                        var cc=1;

                                        this.showInformationDialog("Валюта не совпадает с ранее выбранной");

                                    }

                                   else this.callParent(arguments);

то возникает ошибка (Cannot read property 'superclass' of undefined)

                            

Если this.callParent(arguments) поставить в методе save в конце всей вышеприведенной функции, то тогда предупреждение выводится, но и сохранение также происходит ( а надо, чтобы не происходило)

 

 

 

 

 

Похожий вопрос решают тут.

 

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

Спасибо, помогла связанная тема 

https://community.terrasoft.ru/questions/pereopredelenie-metoda-save-pr…

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