Добрый день. Прошу помощи - третий день мучаюсь с этой задачкой. Есть страница редактирования. В ней есть деталь, отображающая (только чтение) записи из того же реестра. Отбор записей в деталь должен проводиться по ряду условий, связанных с полями основной записи на странице редактирования. Мысль в том, чтобы по этим условиям отобрать через 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 этого недочета лишена.

 

 

 

 

 

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

Собственно насколько я понял по умолчанию запросы с использованием EntitySchemaQuery асинхронны, есть возможность выполнить синхронный  запрос

Нравится

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

Добрый день

Вопрос не понятен. Какая синхронность вам нужна?

Артем Гура,

 esq.getEntityCollection

Ответ - синхронно сделать не получится/ну либо получится, но тогда у пользователя будет виснуть браузер в ожидании ответа сервера (см xmlhttprequest).

Если нужно вручную вызывать нужные функции последовательно - Terrasoft.chain в помощь.

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

Добрый день.

Заместил схемку LeadAccountProfileSchema - вызываю метод FindSimilar при получение сообщения от карточки лида. В методе реализован Terrasoft.chain, чтобы убрать ассинхронность запроса в initSimilarEntityRecordsCollection. Но в chain почему-отрабатывает только первая функция, а onSimilarButtonClick не работает. Почему?

 

 

 

define("LeadAccountProfileSchema", ["LeadAccountProfileSchemaResources", "LeadSimilarEntitiesProfileSchemaUtilities"],
	function(resources) {
		return {
			entitySchemaName: "Account",
			mixins: {},
			attributes: {},
			messages: {
			"FindSimilarAccount": {
			mode: this.Terrasoft.MessageMode.PTP,
			direction: this.Terrasoft.MessageDirectionType.SUBSCRIBE
			}
			},
			methods: {
				initEntity: function() {
					this.callParent(arguments);
					this.sandbox.subscribe("FindSimilarAccount", this.FindSimilar, this, ["123"]);
				},
				FindSimilar: function() {
					this.Terrasoft.chain(
					this.initSimilarEntityRecordsCollection,
					this.onSimilarButtonClick,
					this)
				}
			},
			};
	});

 

Нравится

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

Метод, находящийся в chain должен принимать и вызывать после выполнения логики callback:

 

initSimilarEntityRecordsCollection: function(callback, scope) {
    // Logic
	if (callback) {
		callback.call(scope || this);
	}
},

 

Толмачев Дмитрий Юрьевич,

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

СД,

попробуйте примерно вот так через next:

Terrasoft.chain(
	function (next) {
		// какие-то действия
		next();
	},
	function(next) {
		// либо в callback
		var config = {
			isSilent: true,
			callback: next
		};
		this.save(config, false);
	}
}

 

СД,

Это просто пример. Вы же спросили почему у вас не выполняет вторая функция. Не выполняется, т.к. не вызывается. Вызвать можно через callback или next.

Конечно блок вызова callback-метода должен находиться в месте получения ответа от первой функции для реализации последовательного вызова.

  

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