Фильтр детали на основе результатов EntitySchemaQuery

Добрый день. Прошу помощи - третий день мучаюсь с этой задачкой. Есть страница редактирования. В ней есть деталь, отображающая (только чтение) записи из того же реестра. Отбор записей в деталь должен проводиться по ряду условий, связанных с полями основной записи на странице редактирования. Мысль в том, чтобы по этим условиям отобрать через EntitySchemaQuery несколько Id и назначить их в фильтр детали через createColumnInFilterWithParameters.

Проблема в том, что результаты EntitySchemaQuery.getEntityCollection отрабатываются в callback-функции, и происходит это в большинстве случаев позже, чем завершается работа функции filterMethod детали, в которой делается вызов getEntityCollection. Фильтр получается пустым.

Ниже проблемный код:

// функция назначена как "filterMethod" детали
applyFilter: function() {
    //
    var vFGroup = Terrasoft.createFilterGroup();
    vFGroup.logicalOperation = Terrasoft.LogicalOperatorType.AND;

    //

    var esq = Ext.create("Terrasoft.EntitySchemaQuery", {
        rootSchemaName: "Tenants"
    });

    esq.addColumn("Id");
    esq.addColumn("ReportMonth");
    esq.addColumn("Area");

    var vArea = this.get("Area");

    // фильтры запроса - должна совпадать дата, и площадь быть в +-20%                    
    esq.filters.add("ReportMonthFilter", 
        esq.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, 
            "ReportMonth", this.get("ReportMonth")));
    esq.filters.add("AreaFilter", 
        esq.createColumnBetweenFilterWithParameters("Area", 
            vArea * 0.8, vArea * 1.2));

    // до этого места все работает корректно 
    // теперь запускаем запрос и получаем данные
     // насколько я понимаю, архитектурно система распараллеливает задачи,
    // т.е. function(result) и следующая инструкция после getEntityCollection()
    // начинают отрабатываться одновременно
    esq.getEntityCollection(function (result) {
        if (result.success) {

            // добавляем фильтр как UID по списку
            // здесь так можно, больших выборок не предполагается
            var vSelected = [];                        
            result.collection.each(function (item) {
                vSelected.push(item.get("Id"));
            });

            var vIdF = Terrasoft.createColumnInFilterWithParameters("Id", vSelected);

            // нужно как-то гарантировать, чтобы эта операция всегда выполнялась раньше, чем 
            // return vFGroup; в конце функции. Иначе в фильтры попадает пустой список, и фильтр
            // не работает. 
            vFGroup.add("vIdF", vIdF);
        }
    }, this);

    // Интересно, что при первом открытии детали после обновления 
    // страницы операция return vFGroup; 
    // выполняется корректно, т.е. после vFGroup.add("vIdF", vIdF);. 
    //Если дальше закрыть страницу и через реестр
    // открыть другую запись - уже не работает.

    // Также интересно, что если вбить вот сюда:
    // window.alert("!");
    // то пауза будет достаточна для формирования vFGroup 
    // независимо от того, в первый раз я открываю
    // запись или нет

    return vFGroup;
},

 

Нравится

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

Согласен с Александр Зверев
Недавно сам мучался с подобным, гораздо приятнее когда вся логика связок таблиц завернута во фьюху.
Главное не забыть что во фьюхе должны быть также служебные поля:

DROP VIEW IF EXISTS dbo.VwCaseGroup
GO

CREATE VIEW dbo.VwCaseGroup
AS SELECT
  SAU.ContactId AS Id,
  SUR.SysRoleId,
  SUR.CreatedById,---------<
  SUR.ModifiedById,---------<
  SUR.CreatedOn,---------<
  SUR.ModifiedOn,---------<
  SUR.ProcessListeners---------<
FROM dbo.SysAdminUnit SAU
JOIN dbo.SysUserInRole SUR ON SAU.Id = SUR.SysUserId
GO

Сорри, уже сам разобрался. Надо было всего-то создать property для списка UID и перенести его подгрузку в onEntityInitialized, оставив в applyFilter только сортировку и создание итогового фильтра для детали. 

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

Юрий, вообще, такая постановка намекает, что можно в БД сделать view с нужными данными: каждому Id записи в основном разделе будет соответствовать несколько строк для отображения на детали по нужному условию.

 

Создать объект с такими же колонками, привязать к этой view и далее в разделе настроить деталь стандартными средствами без всякого кода.

Согласен с Александр Зверев
Недавно сам мучался с подобным, гораздо приятнее когда вся логика связок таблиц завернута во фьюху.
Главное не забыть что во фьюхе должны быть также служебные поля:

DROP VIEW IF EXISTS dbo.VwCaseGroup
GO

CREATE VIEW dbo.VwCaseGroup
AS SELECT
  SAU.ContactId AS Id,
  SUR.SysRoleId,
  SUR.CreatedById,---------<
  SUR.ModifiedById,---------<
  SUR.CreatedOn,---------<
  SUR.ModifiedOn,---------<
  SUR.ProcessListeners---------<
FROM dbo.SysAdminUnit SAU
JOIN dbo.SysUserInRole SUR ON SAU.Id = SUR.SysUserId
GO

Генин Юрий,

На всякий случай, для будущих читателей этого треда: вариант с EntitySchemaQuery плох тем, что при больших выборках не успевает отработать до открытия пользователем вкладки с деталью, что приводит к визуальному отсутствию фильтрации. Схема с VIEW этого недочета лишена.

 

 

 

 

 

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