Вопрос

Добрый день, коллеги. Необходимо чтобы в разделе была сгенерирована деталь с полями (описание, тип оплаты, сумма,  файл (фото_чека.jpg/png/pdf)).

В разделе есть деталь "Файл и ссылка объекта Продажи". Добавляю колонки тип оплаты, сумма. Затем замещаю схему FileDetailV2 и добавляю в него код для того, чтобы была возможность настроить колонки для детали. Настраиваю колонки и они показываются на странице, но заполнить добавленные поля (тип оплаты, сумма) не получается потому что на карточке редактирования их нет (там только стандартные поля Название и описание).

Вопрос: как добавить созданные поля в карточку?

У меня такой же вопрос

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

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

Григорий Чех,

Не подскажите, как создать эту карточку?

Артём Иванов Иванович,

в мастере раздела создается новая страница редактирования на первой странице

Натали Вишня,

Это очевидно не то, что мне нужно.

Добавить нужные колонки и отобразить их получилось:

Но какую страницу заместить, чтобы добавить в эту карточку необходимые колонки (сумма) 

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

Имеется иерархическая деталь с редактируемым реестром. В ней возникает проблема при сохранении дробного числа. Появляется ошибка Cannot read property 'getAttribute' of null, которая возникает в результате того, что метод GetDomRow возвращает undefined. После этого я не могу больше сохранять дробные числа в реестре и приходится перезагружать страницу. Первое сохранение проходит удачно, хоть и успевает появиться ошибка. В результате чего возникает такая проблема? ниже представлен код детали

define("IDSBRefrigeratorInTMADetail",
    ["ConfigurationGrid", "ConfigurationGridGenerator", "ConfigurationGridUtilities", "ServiceHelper"],
    function (ConfigurationGrid, ConfigurationGridGenerator, ConfigurationGridUtilities, ServiceHelper) {
        return {
            messages: {
                "ReloadRefrigeratorsInTMAGrid": {
                    "mode": Terrasoft.MessageMode.BROADCAST,
                    "direction": Terrasoft.MessageDirectionType.SUBSCRIBE
                }
            },
            entitySchemaName: "IDSBRefrigeratorInTMA",
            attributes: {
                "IsEditable": {
                    dataValueType: Terrasoft.DataValueType.BOOLEAN,
                    type: Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
                    value: true
                }
            },
            mixins: {
                ConfigurationGridUtilities: "Terrasoft.ConfigurationGridUtilities"
            },
            details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
            diff: /**SCHEMA_DIFF*/[
                {
                    "operation": "merge",
                    "name": "DataGrid",
                    "values": {
                        "hierarchical": true,
                        "hierarchicalColumnName": "IDSBParent",
                        "className": "Terrasoft.ConfigurationGrid",
                        "generator": "ConfigurationGridGenerator.generatePartial",
                        "generateControlsConfig": { "bindTo": "generateActiveRowControlsConfig" },
                        "changeRow": { "bindTo": "changeRow" },
                        "unSelectRow": { "bindTo": "unSelectRow" },
                        "onGridClick": { "bindTo": "onGridClick" },
                        "activeRowAction": { "bindTo": "onActiveRowAction" },
                        "initActiveRowKeyMap": { "bindTo": "initActiveRowKeyMap" },
                        "multiSelect": false
                    }
                },
                {
                    "operation": "remove",
                    "name": "AddRecordButton"
                }]/**SCHEMA_DIFF*/,
            methods: {
                generateActiveRowControlsConfig: function (id, columnsConfig, rowConfig) {
                    this.columnsConfig = columnsConfig;
                    var gridData = this.getGridData();
                    var activeRow = gridData.get(id);
                    var isEditableColumn;
                    if (activeRow.values.IDSBParent === "") {
                        isEditableColumn = this.ParentColumnIsEditable;
                    }
                    else {
                        isEditableColumn = this.ColumnIsEditable;
                    }
                    var gridLayoutItems = [];
                    var currentColumnIndex = 0;
                    Terrasoft.each(columnsConfig, function (columnConfig) {
                        var cellConfig = this.getActiveRowCellConfig(columnConfig, currentColumnIndex);
                        cellConfig.enabled = isEditableColumn(cellConfig.name);
                        if (!cellConfig.hasOwnProperty("isNotFound")) {
                            gridLayoutItems.push(cellConfig);
                        }
                        currentColumnIndex += cellConfig.layout.colSpan;
                    }, this);
                    this.applyBusinessRulesForActiveRow(id, gridLayoutItems);
                    var viewGenerator = Ext.create(this.getRowViewGeneratorClassName());
                    viewGenerator.viewModelClass = this;
                    var gridLayoutConfig = viewGenerator.generateGridLayout({
                        name: this.name,
                        items: gridLayoutItems
                    });
                    rowConfig.push(gridLayoutConfig);
                },
                ParentColumnIsEditable: function (columnName) {
                    return (columnName === "IDSBPlacementPrice" || columnName === "IDSBNumberOfDoors" || columnName === "IDSBProlongation");
                },
                ColumnIsEditable: function (columnName) {
                    return (columnName === "IDSBRBBottlePlan" || columnName === "IDSBRBBottleCurrent"
                        || columnName === "IDSBBRBottlePlan" || columnName === "IDSBBRBottleCurrent");
                },
                init: function () {
                    this.callParent(arguments);
                    this.set("IsPageable", false);
                    this.set("RowCount", 28000);
                    this.sandbox.subscribe("ReloadRefrigeratorsInTMAGrid", this.onReloadRefrigeratorsInTMAGrid, this);
                },
                onReloadRefrigeratorsInTMAGrid: function (args) {
                    var id = this.get("MasterRecordId");
                    debugger;
                    if (id === args) {
                        this.reloadGridData();
                    }
                },
                addGridDataColumns: function (esq) {
                    this.callParent(arguments);
                    if (!esq.columns.contains("IDSBParent")) {
                        esq.addColumn("IDSBParent");
                    }
                },
                getGridDataColumns: function () {
                    var gridDataColumns = this.callParent(arguments);
                    if (!gridDataColumns.IDSBParent) {
                        gridDataColumns.IDSBParent = {
                            path: "IDSBParent"
                        };
                    }
                    return gridDataColumns;
                },
                addToolsButtonMenuItems: function (toolsButtonMenu) {
                    this.addGridOperationsMenuItems(toolsButtonMenu);
                    if (this.useDetailWizard) {
                        this.addDetailWizardMenuItems(toolsButtonMenu);
                    }
                },
                prepareResponseCollection: function (collection) {
                    collection.each(function (item) {
                        var parent = item.get("IDSBParent");
                        var parentId = parent && parent.value;
                        if (parentId) {
                            item.set("IDSBParentId", parentId);
                        }
                        Terrasoft.each(item.columns, function (column) {
                            this.addColumnLink(item, column);
                            this.applyColumnDefaults(column);
                        }, this);
                    }, this);
                }
            }
        };
    });

У меня такой же вопрос

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

Навряд ли кто то взглянув на не один десяток строк кода ответит вам почему возникает проблема при сохранении (скорее всего редактируемость и иерархичность не совместимы).

В любом случае вам может помочь только отладка кода!

решил задачу тупо влоб, переопределив метод сохранения. Написал своё сохранение, вызывая сервис из сервера. немного медленно, но работает

saveRowChanges: function (row, callback, scope) {
                    scope = scope || this;
                    callback = callback || Terrasoft.emptyFn;
                    if (row && this.getIsRowChanged(row)) {
                        if (row.values.IDSBParent !== "") {
                            this.saveChildRow(row, callback, scope);
                        }
                        else {
                            this.saveParentRow(rowm, callback, scope);
                        }
                    } else {
                        callback.call(scope);
                    }
                },
saveChildRow: function (row, callback, scope) {
                    var changed = row.changedValues;
                    debugger;
                    if (!changed.hasOwnProperty("IDSBBRBottleCurrent")) {
                        changed.IDSBBRBottleCurrent = row.values.IDSBBRBottleCurrent;
                    }
                    if (!changed.hasOwnProperty("IDSBBRBottlePlan")) {
                        changed.IDSBBRBottlePlan = row.values.IDSBBRBottlePlan;
                    }
                    if (!changed.hasOwnProperty("IDSBRBBottlePlan")) {
                        changed.IDSBRBBottlePlan = row.values.IDSBRBBottlePlan;
                    }
                    if (!changed.hasOwnProperty("IDSBRBBottleCurrent")) {
                        changed.IDSBRBBottleCurrent = row.values.IDSBRBBottleCurrent;
                    }
                    callback = this.reloadGridData;
                    var serviceSaveData = {
                        RowId: row.values.Id,
                        bottles: changed
                    }
                    ServiceHelper.callService("IDSBPlacingREService", "SaveChildRow",
                        callback, serviceSaveData, scope);
                }

 

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

Создал иерархическую деталь с редактируемым реестром. Но появилась проблема при количестве дочерних элементов больше 8. Они почему не отображаются, выдается ошибка Cannot read property 'getAttribute' of null. В БД всё верно. 

Вот код детали

define("IDSBRefrigeratorInTMADetail",
    ["ConfigurationGrid", "ConfigurationGridGenerator", "ConfigurationGridUtilities"],
    function () {
        return {
            messages: {
                "ReloadRefrigeratorsInTMAGrid": {
                    "mode": Terrasoft.MessageMode.BROADCAST,
                    "direction": Terrasoft.MessageDirectionType.SUBSCRIBE
                }
            },
            entitySchemaName: "IDSBRefrigeratorInTMA",
            attributes: {
                "IsEditable": {
                    dataValueType: Terrasoft.DataValueType.BOOLEAN,
                    type: Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
                    value: true
                }
            },
            mixins: {
                ConfigurationGridUtilities: "Terrasoft.ConfigurationGridUtilities"
            },
            details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
            diff: /**SCHEMA_DIFF*/[
                {
                    "operation": "merge",
                    "name": "DataGrid",
                    "values": {
                        "hierarchical": true,
                        "hierarchicalColumnName": "IDSBParent",
                        "maxColumns": 48,
                        "maxRowsCount": 10000,
                        "className": "Terrasoft.ConfigurationGrid",
                        "generator": "ConfigurationGridGenerator.generatePartial",
                        "generateControlsConfig": { "bindTo": "generateActiveRowControlsConfig" },
                        "changeRow": { "bindTo": "changeRow" },
                        "unSelectRow": { "bindTo": "unSelectRow" },
                        "onGridClick": { "bindTo": "onGridClick" },
                        "activeRowAction": { "bindTo": "onActiveRowAction" },
                        "initActiveRowKeyMap": { "bindTo": "initActiveRowKeyMap" },
                        "multiSelect": false
                    }
                },
                {
                    "operation": "remove",
                    "name": "AddRecordButton"
                }]/**SCHEMA_DIFF*/,
            methods: {
                generateActiveRowControlsConfig: function (id, columnsConfig, rowConfig) {
                    this.columnsConfig = columnsConfig;
                    var gridData = this.getGridData();
                    var activeRow = gridData.get(id);
                    var isEditableColumn;
                    if (activeRow.values.IDSBParent === "") {
                        isEditableColumn = this.isEditableParentColumn;
                    }
                    else {
                        isEditableColumn = this.isEditableColumn;
                    }
                    var gridLayoutItems = [];
                    var currentColumnIndex = 0;
                    Terrasoft.each(columnsConfig, function (columnConfig) {
                        var cellConfig = this.getActiveRowCellConfig(columnConfig, currentColumnIndex);
                        cellConfig.enabled = isEditableColumn(cellConfig.name);
                        if (!cellConfig.hasOwnProperty("isNotFound")) {
                            gridLayoutItems.push(cellConfig);
                        }
                        currentColumnIndex += cellConfig.layout.colSpan;
                    }, this);
                    this.applyBusinessRulesForActiveRow(id, gridLayoutItems);
                    var viewGenerator = Ext.create(this.getRowViewGeneratorClassName());
                    viewGenerator.viewModelClass = this;
                    var gridLayoutConfig = viewGenerator.generateGridLayout({
                        name: this.name,
                        items: gridLayoutItems
                    });
                    rowConfig.push(gridLayoutConfig);
                },
                isEditableParentColumn: function (columnName) {
                    return false;
                },
                isEditableColumn: function (columnName) {
                    return (columnName === "IDSBBottlePlan");
                }/*,
                init: function () {
                    this.callParent(arguments);
                    this.sandbox.subscribe("ReloadRefrigeratorsInTMAGrid", this.onReloadRefrigeratorsInTMAGrid, this);
                },
                onReloadRefrigeratorsInTMAGrid: function (args) {
                    this.reloadGridData();
                }*/
            }
	};
});

 

У меня такой же вопрос

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

Для упрощения отладки посмотрите SQL профайлером запросы которые отправляются в БД.

Григорий Чех, думаете нужно заместить метод addGridDataColumns?

Григорий имел в виду использование профайлера. Естественно, только для случаев, когда есть доступ к серверу БД.

посмотрел профайлер. Выполняется следующий запрос. Забил его сам в SQL Management. Выдал недостающие элементы, которые как раз невыведены на экран. Ошибка возникает когда нажимаю "Показать больше"

SELECT
	[IDSBRefrigeratorInTMA].[Id] [Id],
	[IDSBRefrigeratorInTMA].[IDSBStreet] [IDSBStreet],
	[IDSBRefrigeratorInTMA].[IDSBCustomerInTMAId] [IDSBCustomerInTMAId],
	[IDSBRefrigeratorInTMA].[ITTradeMarketId] [ITTradeMarketId],
	[ITTradeMarket].[ITName] [ITTradeMarket.ITName],
	[IDSBRefrigeratorInTMA].[MonthId] [MonthId],
	[Month].[Name] [Month.Name],
	[IDSBRefrigeratorInTMA].[IDSBBottlePlan] [IDSBBottlePlan],
	[IDSBRefrigeratorInTMA].[IDSBParentId] [IDSBParentId],
	[IDSBParent].[IDSBStreet] [IDSBParent.IDSBStreet],
	[ITTradeMarket].[ITTypeId] [ITTradeMarket.ITTypeId],
	[ITType].[Name] [ITType.Name],
	(
SELECT
	COUNT([SubEntryPoint].[Id]) [Count]
FROM
	[dbo].[EntryPoint] [SubEntryPoint] WITH(NOLOCK)
WHERE
	[SubEntryPoint].[EntityId] = [IDSBRefrigeratorInTMA].[Id]
	AND [SubEntryPoint].[IsActive] = 1) [SubEntryPoint],
	[IDSBRefrigeratorInTMA].[CreatedOn] [CreatedOn],
	[IDSBRefrigeratorInTMA].[CreatedById] [CreatedById],
	[CreatedBy].[Name] [CreatedBy.Name],
	[CreatedBy].[PhotoId] [CreatedBy.PhotoId],
	[IDSBRefrigeratorInTMA].[ModifiedOn] [ModifiedOn],
	[IDSBRefrigeratorInTMA].[ModifiedById] [ModifiedById],
	[ModifiedBy].[Name] [ModifiedBy.Name],
	[ModifiedBy].[PhotoId] [ModifiedBy.PhotoId],
	[IDSBRefrigeratorInTMA].[ProcessListeners] [ProcessListeners]
FROM
	[dbo].[IDSBRefrigeratorInTMA] [IDSBRefrigeratorInTMA] WITH(NOLOCK)
	LEFT OUTER JOIN [dbo].[ITTradeMarket] [ITTradeMarket] WITH(NOLOCK) ON ([ITTradeMarket].[Id] = [IDSBRefrigeratorInTMA].[ITTradeMarketId])
	LEFT OUTER JOIN [dbo].[Month] [Month] WITH(NOLOCK) ON ([Month].[Id] = [IDSBRefrigeratorInTMA].[MonthId])
	LEFT OUTER JOIN [dbo].[IDSBRefrigeratorInTMA] [IDSBParent] WITH(NOLOCK) ON ([IDSBParent].[Id] = [IDSBRefrigeratorInTMA].[IDSBParentId])
	LEFT OUTER JOIN [dbo].[ITITTradeMarketType1] [ITType] WITH(NOLOCK) ON ([ITType].[Id] = [ITTradeMarket].[ITTypeId])
	LEFT OUTER JOIN [dbo].[Contact] [CreatedBy] WITH(NOLOCK) ON ([CreatedBy].[Id] = [IDSBRefrigeratorInTMA].[CreatedById])
	LEFT OUTER JOIN [dbo].[Contact] [ModifiedBy] WITH(NOLOCK) ON ([ModifiedBy].[Id] = [IDSBRefrigeratorInTMA].[ModifiedById])
WHERE
	[IDSBRefrigeratorInTMA].[ITTradeMarketId] = '54368FDE-6D00-4BDE-BAAE-EDEA56EBAA33'
ORDER BY
	[Id] ASC OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY

 

Может, 8 элементов видно как раз из-за выборки порциями по 10? Судя по окончанию SQL-запроса, это как раз вторая десятка, первая пропущена.

А где именно вылетает «Cannot read property 'getAttribute' of null», полный стек не видно?

Вылетает на этом методе. В строке var n = this.getDomRow(i) в n кладется undefined и далее соответственно вылетает ошибка. В i в этот момент родительская колонка

onCollectionDataLoaded: function(e, t, a) {
        if (this.theoreticallyActiveRows = null,
        !this.rows.length)
            return this.collection = this.collection || e,
            this.prepareCollectionData(),
            void this.safeRerender();
        if (!Ext.Object.isEmpty(t) && this.rendered) {
            var r = []
              , s = {
                rows: r
            };
            if (t.each(function(e) {
                this.prepareCollectionItem(e);
                var t = this.getRow(e);
                r.push(t),
                a && ("top" !== a.mode ? this.rows.push(t) : this.rows.splice(0, 0, t))
            }, this),
            this.hierarchical && !t.isEmpty()) {
                var i = t.getByIndex(0).get(this.hierarchicalColumnName);
                if (s[this.hierarchicalColumnName] = i,
                "listed" === this.type && i) {
                    var n = this.getDomRow(i)
                      , o = parseInt(n.getAttribute("level"), 10);
                    s.rowLevel = o + 1
                }
            }
            var l = [];
            this.renderGrid(l, s);
            for (var c = "", h = 0, u = l.length; h < u; h += 1)
                c += Ext.DomHelper.createHtml(l[h]);
            Ext.Object.isEmpty(a) && (a = {
                mode: "bottom"
            }),
            this.addRows(c, a),
            this.checkNeedLoadData()
        }
    },

 

Что-то не могу найти такой функции в «коробке».

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

Если убираю редактируемость, ошибка не исчезает. Если убираю иерархичность, всё отображается нормально

Это логично, если сбой при превышении 8 потомков. В плоской детали никаких потомков нет. Сравните с другими иерархическими деталями, есть там такое ограничение или нет?

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

init: function () {
                    this.callParent(arguments);
                    this.set("IsPageable", false);
                    this.set("RowCount", 28000);
                    this.sandbox.subscribe("ReloadRefrigeratorsInTMAGrid", this.onReloadRefrigeratorsInTMAGrid, this);
                },

 

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

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

Добрый день.

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

Но почему-то при добавлении не чего не происходит.

Прикрепленные файлы
zadacha.png89.04 КБ
код.png49.45 КБ

У меня такой же вопрос

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

Должно выглядить вот так

Ужк обсуждалось тут

Григорий Чех пишет:

Ужк обсуждалось тут

Там не то что мне нужно. У меня реестр детали с 2 справочными полями. При нажатии на одно из них должно открыться окно с данными вкладками.

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

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

Добрый день! подскажите пжлст, каким способом можно применить маску номера для строк на детали с редактируемым реестром. Методы, которые работают для нумерации строк для обычной детали, в данном случае не работают.

Спасибо!

У меня такой же вопрос

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

По идее если использовать формирование номер на событийном БП  (штатно как описано в документации) то после сохранения он должен отображатся на детали, посмотрите тут (Алгоритм реализации кейса на стороне сервера)

 

"Методы, которые работают для нумерации строк для обычной детали, в данном случае не работают"  - а что это за методы? Просто нигде в базовых версиях не видел нумерации строк в гриде.

Варфоломеев Данила,

Наверное речь о формировании номера для объекта по маске по аналогии с тем как это делается в карточке редактирования открываемой из реестра. 

По идее если использовать формирование номер на событийном БП  (штатно как описано в документации) то после сохранения он должен отображатся на детали, посмотрите тут (Алгоритм реализации кейса на стороне сервера)

 

Добрый день, коллеги! Спасибо за обратную связь!  

Да,но  Заказчику в данном случае получать номера строк после обновления карточки в данном случае не подходит. 

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

Я смотрю в решении Террасофта с маркета в Конструкторе отчетов даже это не сделано… там всегда проставляется по умолчанию просто 1… и далее ты сам сидишь и нумеруешь.

 

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

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

Добрый день.
Необходимо в редактируемом реестре добавить свойство enabled для поля по условию.
Атрибут условия вычисляется в методе onEntityInitialized Схемы редактирования детали.
Но при загрузке редактируемого реестра ни метод init, ни onEntityInitialized  ни бизнес-правила не отрабатывают.
Как быть в такой ситуации?
 

У меня такой же вопрос

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

Игорь, привет!

Была подобная ситуация - нужно было забиндить enabled поля на поле в связанном справочнике. Делал примерно так:

1. На странице редактирования добавил attribute с именем "{Имя_справочного_поля}.{Имя_колонки_в_справочнике}". Значение его проставлял в onEntityInitialized, и enebled колонки завязал бизнес-правилом на этот аттрибут.

2. На странице детали детали в методе addGridDataColumns добавлял колонку с таким же именем как и аттрибут на странице редактирования (у меня там было bool) и вауля.

 

Дело в том, что правила работают, но в редактируемом реестре происходит поиск свойства (на которое ты забиндил enabled) в колонках текущей строки, соответственно если такой колонки нет в строке, получается как получается.

Костыль, конечно, но попробовать стоит. Если есть более правильный способ - тоже интересно)

Игорь, привет!

Была подобная ситуация - нужно было забиндить enabled поля на поле в связанном справочнике. Делал примерно так:

1. На странице редактирования добавил attribute с именем "{Имя_справочного_поля}.{Имя_колонки_в_справочнике}". Значение его проставлял в onEntityInitialized, и enebled колонки завязал бизнес-правилом на этот аттрибут.

2. На странице детали детали в методе addGridDataColumns добавлял колонку с таким же именем как и аттрибут на странице редактирования (у меня там было bool) и вауля.

 

Дело в том, что правила работают, но в редактируемом реестре происходит поиск свойства (на которое ты забиндил enabled) в колонках текущей строки, соответственно если такой колонки нет в строке, получается как получается.

Костыль, конечно, но попробовать стоит. Если есть более правильный способ - тоже интересно)

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

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

Всем привет!

Столкнулся с проблемой реализации фильтра в справочном поле в детали с редактируемым реестром: нужно делать запрос в БД для получения значения из карточки и в зависимости от этого строить фильтр. Как победить асинхронность?

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

У меня такой же вопрос

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

Дмитрий, почти любую фильтрацию (даже сложную) справочного поля можно сделать с использованием атрибута filters колонки (подробнее в https://academy.terrasoft.ru/documents/technic-sdk/7-13/primenenie-filt…). Для отладки фильтра рекомендую отследить запросы в SQL Server Profiler

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

Дмитрий, почти любую фильтрацию (даже сложную) справочного поля можно сделать с использованием атрибута filters колонки (подробнее в https://academy.terrasoft.ru/documents/technic-sdk/7-13/primenenie-filt…). Для отладки фильтра рекомендую отследить запросы в SQL Server Profiler

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

На странице добавлены две детали с редактируемым реестром. Создал первую и понял, что неправильно. Потом создал вторую корректно и захотел первую удалить (создавал кодом). В мастере ее удалить нельзя. Открыл конфигурацию и удалил строки из схемы раздела, а именно details и diff, касающихся этой детали. Сохранил и очистил кэш. После этого перестали отображаться детали вообще и в консоли появилась ошибка cannot read property "findPrimary". После возвращения кода детали обе появились и работают. Как убрать первую деталь? 

У меня такой же вопрос

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

Очень похоже, что как-то не так удаляете деталь со страницы. Если корректно удалить из details и diff, делать должна удалиться.

Очень похоже, что как-то не так удаляете деталь со страницы. Если корректно удалить из details и diff, делать должна удалиться.

Тёскин Дмитрий Валерьевич,

Проблема в том, что даже ошибиться негде

Вот код страницы полностью:
define("UsrConcertProgram1Page", [],
function() {
    return {
        entitySchemaName: "UsrConcertProgram",
        attributes: {
            "UsrActiveEveryday": {
                    "dataValueType": Terrasoft.DataValueType.INTEGER,
                    "type": Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
                    "caption": "UsrActiveEveryday",
                    "value" : "0"
                }
        },
        modules: /**SCHEMA_MODULES*/{}/**SCHEMA_MODULES*/,
        details: /**SCHEMA_DETAILS*/{
            "Files": {
                "schemaName": "FileDetailV2",
                "entitySchemaName": "UsrConcertProgramFile",
                "filter": {
                    "masterColumn": "Id",
                    "detailColumn": "UsrConcertProgram"
                }
            },
            "UsrPerformanceDetail": {
                "schemaName": "UsrPerformanceDetail",
                "entitySchemaName": "UsrPerformance",
                "filter": {
                    "detailColumn": "UsrConcertProgram",
                    "masterColumn": "Id"
                },
            },
            "UsrSchema1Detail660d66ee": {
                "schemaName": "UsrSchema1Detail",
                "entitySchemaName": "UsrConcertPerformance",
                "filter": {
                    "detailColumn": "UsrConcertProgram",
                    "masterColumn": "Id"
                }
            }
        }/**SCHEMA_DETAILS*/,
        businessRules: /**SCHEMA_BUSINESS_RULES*/{}/**SCHEMA_BUSINESS_RULES*/,
        methods: {
            getActiveEverydayConcerts: function() {
                var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
                    rootSchemaName: "UsrConcertProgram"
                });
                
                var filterGroup = this.Terrasoft.createFilterGroup();
                
                filterGroup.logicalOperation = this.Terrasoft.LogicalOperatorType.AND;
                filterGroup.add("concertsIsActive",
                this.Terrasoft.createColumnFilterWithParameter(this.Terrasoft.ComparisonType.EQUAL, "UsrIsActive", "1"));
                filterGroup.add("performancePeriodEveryday",
                this.Terrasoft.createColumnFilterWithParameter(this.Terrasoft.ComparisonType.EQUAL,
                "UsrPerformancePeriod", "85A8C133-FF83-4290-9F69-B34EAF627F8C"));
                
                esq.filters = filterGroup;
                
                esq.getEntityCollection(function(result) {
                    if (result.success)
                    {
                        this.set("UsrActiveEveryday", result.collection.getCount());
                    }
                }, this);
            },
            maxEverydayActive: function() {
                var invalidMessage = "";
                var maxActiveEverydayConcertCount = 0;
                var activeEverydayConcertCount = this.get("UsrActiveEveryday");
                this.Terrasoft.SysSettings.querySysSettingsItem("UsrMaxEverydayActiveProgram", function(value) {
                    maxActiveEverydayConcertCount = value;
                }, this);
                
                if (this.get("UsrPerformancePeriod").value == "85A8C133-FF83-4290-9F69-B34EAF627F8C".toLowerCase() &&
                this.get("UsrIsActive") && (activeEverydayConcertCount > maxActiveEverydayConcertCount) && !this.isAddMode()) {
                    invalidMessage = "Допускается не более " + maxActiveEverydayConcertCount +
                    " активных ежедневных концертных программ.";
                }
                if(this.get("UsrPerformancePeriod").value == "85A8C133-FF83-4290-9F69-B34EAF627F8C".toLowerCase() &&
                this.get("UsrIsActive") && (activeEverydayConcertCount >= maxActiveEverydayConcertCount) && this.isAddMode()) {
                    invalidMessage = "Допускается не более " + maxActiveEverydayConcertCount +
                    " активных ежедневных концертных программ.";
                }
                return {
                    fullInvalidMessage: invalidMessage,
                    invalidMessage: invalidMessage
                };
            },
            setValidationConfig: function() {
                this.callParent(arguments);
                this.addColumnValidator("UsrIsActive", this.maxEverydayActive);
                this.addColumnValidator("UsrPerformancePeriod", this.maxEverydayActive);
            },
            onEntityInitialized: function() {
                this.callParent(arguments);
                this.getActiveEverydayConcerts();
            }
        },
        dataModels: /**SCHEMA_DATA_MODELS*/{}/**SCHEMA_DATA_MODELS*/,
        diff: /**SCHEMA_DIFF*/[
            {
                "operation": "insert",
                "name": "UsrName9ed0e254-4ab5-4862-9e79-b18e052d92ab",
                "values": {
                    "layout": {
                        "colSpan": 24,
                        "rowSpan": 1,
                        "column": 0,
                        "row": 0,
                        "layoutName": "ProfileContainer"
                    },
                    "bindTo": "UsrName"
                },
                "parentName": "ProfileContainer",
                "propertyName": "items",
                "index": 0
            },
            {
                "operation": "insert",
                "name": "STRING3bea7972-86d7-4d0e-b4d7-5731d5a6a6b6",
                "values": {
                    "layout": {
                        "colSpan": 24,
                        "rowSpan": 1,
                        "column": 0,
                        "row": 1,
                        "layoutName": "ProfileContainer"
                    },
                    "bindTo": "UsrConcertCode",
                    "enabled": true
                },
                "parentName": "ProfileContainer",
                "propertyName": "items",
                "index": 1
            },
            {
                "operation": "insert",
                "name": "LOOKUP2c6c3d90-34b5-4a43-9b28-26c5c29c6c48",
                "values": {
                    "layout": {
                        "colSpan": 24,
                        "rowSpan": 1,
                        "column": 0,
                        "row": 2,
                        "layoutName": "ProfileContainer"
                    },
                    "bindTo": "UsrOwner",
                    "enabled": true,
                    "contentType": 3
                },
                "parentName": "ProfileContainer",
                "propertyName": "items",
                "index": 2
            },
            {
                "operation": "insert",
                "name": "UsrIsActive3354c9f0-c35f-4c7c-85ec-0b3cc01376b8",
                "values": {
                    "layout": {
                        "colSpan": 12,
                        "rowSpan": 1,
                        "column": 0,
                        "row": 0,
                        "layoutName": "Header"
                    },
                    "bindTo": "UsrIsActive"
                },
                "parentName": "Header",
                "propertyName": "items",
                "index": 0
            },
            {
                "operation": "insert",
                "name": "CreatedOn770eb82e-0b06-4f93-be35-bdd0ddac28b8",
                "values": {
                    "layout": {
                        "colSpan": 12,
                        "rowSpan": 1,
                        "column": 12,
                        "row": 0,
                        "layoutName": "Header"
                    },
                    "bindTo": "CreatedOn"
                },
                "parentName": "Header",
                "propertyName": "items",
                "index": 1
            },
            {
                "operation": "insert",
                "name": "UsrActiveEveryday",
                "values": {
                    "bindTo": "getActiveEverydayConcerts",
                    "caption": "UsrActiveEveryday",
                    "layout": {
                        "colSpan": 12,
                        "rowSpan": 1,
                        "column": 0,
                        "row": 1
                    }
                },
                "parentName": "Header",
                "propertyName": "items",
                "index": 2
            },
            {
                "operation": "insert",
                "name": "Tab75eff25dTabLabel",
                "values": {
                    "caption": {
                        "bindTo": "Resources.Strings.Tab75eff25dTabLabelTabCaption"
                    },
                    "items": []
                },
                "parentName": "Tabs",
                "propertyName": "tabs",
                "index": 0
            },
            {
                "operation": "insert",
                "name": "Tab75eff25dTabLabelGroup46c8d52b",
                "values": {
                    "caption": {
                        "bindTo": "Resources.Strings.Tab75eff25dTabLabelGroup46c8d52bGroupCaption"
                    },
                    "itemType": 15,
                    "markerValue": "added-group",
                    "items": []
                },
                "parentName": "Tab75eff25dTabLabel",
                "propertyName": "items",
                "index": 0
            },
            {
                "operation": "insert",
                "name": "Tab75eff25dTabLabelGridLayoutd14f72b6",
                "values": {
                    "itemType": 0,
                    "items": []
                },
                "parentName": "Tab75eff25dTabLabelGroup46c8d52b",
                "propertyName": "items",
                "index": 0
            },
            {
                "operation": "insert",
                "name": "UsrTeama25e968a-f7f0-4c80-bde3-ed860af75538",
                "values": {
                    "layout": {
                        "colSpan": 12,
                        "rowSpan": 1,
                        "column": 0,
                        "row": 0,
                        "layoutName": "Tab75eff25dTabLabelGridLayoutd14f72b6"
                    },
                    "bindTo": "UsrTeam"
                },
                "parentName": "Tab75eff25dTabLabelGridLayoutd14f72b6",
                "propertyName": "items",
                "index": 0
            },
            {
                "operation": "insert",
                "name": "UsrComment8c10205e-2bf8-42d0-b7fa-605cc32a37af",
                "values": {
                    "layout": {
                        "colSpan": 12,
                        "rowSpan": 2,
                        "column": 12,
                        "row": 0,
                        "layoutName": "Tab75eff25dTabLabelGridLayoutd14f72b6"
                    },
                    "bindTo": "UsrComment",
                    "enabled": true,
                    "contentType": 0,
                    "labelConfig": {
                        "caption": {
                            "bindTo": "Resources.Strings.UsrComment8c10205e2bf842d0b7fa605cc32a37afLabelCaption"
                        }
                    }
                },
                "parentName": "Tab75eff25dTabLabelGridLayoutd14f72b6",
                "propertyName": "items",
                "index": 1
            },
            {
                "operation": "insert",
                "name": "UsrPerformancePeriod8fdfacd0-81ef-4bf3-9ccc-4cb9ab0f5b7b",
                "values": {
                    "layout": {
                        "colSpan": 12,
                        "rowSpan": 1,
                        "column": 0,
                        "row": 1,
                        "layoutName": "Tab75eff25dTabLabelGridLayoutd14f72b6"
                    },
                    "bindTo": "UsrPerformancePeriod",
                    "enabled": true,
                    "contentType": 5
                },
                "parentName": "Tab75eff25dTabLabelGridLayoutd14f72b6",
                "propertyName": "items",
                "index": 2
            },
            {
                "operation": "insert",
                "name": "UsrSchema1Detail660d66ee",
                "values": {
                    "itemType": 2,
                    "markerValue": "added-detail"
                },
                "parentName": "TabsContainer",
                "propertyName": "items",
                "index": 1
            },
            {
                "operation": "insert",
                "name": "NotesAndFilesTab",
                "values": {
                    "caption": {
                        "bindTo": "Resources.Strings.NotesAndFilesTabCaption"
                    },
                    "items": []
                },
                "parentName": "Tabs",
                "propertyName": "tabs",
                "index": 1
            },
            {
                "operation": "insert",
                "name": "Files",
                "values": {
                    "itemType": 2
                },
                "parentName": "NotesAndFilesTab",
                "propertyName": "items",
                "index": 0
            },
            {
                "operation": "insert",
                "name": "NotesControlGroup",
                "values": {
                    "itemType": 15,
                    "caption": {
                        "bindTo": "Resources.Strings.NotesGroupCaption"
                    },
                    "items": []
                },
                "parentName": "NotesAndFilesTab",
                "propertyName": "items",
                "index": 1
            },
            {
                "operation": "insert",
                "name": "Notes",
                "values": {
                    "bindTo": "UsrNotes",
                    "dataValueType": 1,
                    "contentType": 4,
                    "layout": {
                        "column": 0,
                        "row": 0,
                        "colSpan": 24
                    },
                    "labelConfig": {
                        "visible": false
                    },
                    "controlConfig": {
                        "imageLoaded": {
                            "bindTo": "insertImagesToNotes"
                        },
                        "images": {
                            "bindTo": "NotesImagesCollection"
                        }
                    }
                },
                "parentName": "NotesControlGroup",
                "propertyName": "items",
                "index": 0
            },
            {
                "operation": "insert",
                "name": "UsrPerformanceDetail",
                "values": {
                    "itemType": 2,
                    "markerValue": "added-detail"
                },
                //"parentName": "TabsContainer",
                "propertyName": "items",
                "index": 2
            }
        ]/**SCHEMA_DIFF*/
    };
});

 

Удаляю я все с деталью UsrPerformanceDetail

 

Можно подойти к решению с другой стороны: откатиться до стандартной страницы из «коробки» без обеих деталей, затем добавить вторую.

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

Коллеги доброго времени суток!

Реализовал деталь с редактируемым реестром и карточкой редактирования записи код ниже:

define("AbAccountProductDetail",
	["ConfigurationEnums", "ConfigurationGrid", "ConfigurationGridGenerator", "ConfigurationGridUtilities"],
	function (enums) {
		return {
			entitySchemaName: "AbAccountProduct",
			attributes: {
				"IsEditable": {
					dataValueType: Terrasoft.DataValueType.BOOLEAN,
					type: Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
					value: true
				}
			},
			mixins: {
				ConfigurationGridUtilities: "Terrasoft.ConfigurationGridUtilities"
			},
			methods:{
				init: function() {
					this.callParent(arguments);
					this.sandbox.subscribe("[AbAccountProductEntityEventListner]:[RequestToPlatform]:[Exception]", this.accountProductEntityListnerMsgHandler, this);
				},
 
				/*Overrided "BaseGridDetailV2"*/
				editRecord: function(record) {
					var activeRow = record || this.getActiveRow();
					if (!activeRow) {
						return;
					}
					if (!this.getIsCardValid()) {
						return;
					}
					var isCardChanged = this.getIsCardChanged();
					var primaryColumnValue = typeof activeRow === "object" ? activeRow.get(activeRow.primaryColumnName) : activeRow;
					var typeColumnValue = this.getTypeColumnValue(activeRow);
					this.setLastActiveRow(primaryColumnValue);
					if (isCardChanged) {
						this.set("CardState", enums.CardStateV2.EDIT);
						this.set("EditPageUId", typeColumnValue);
						this.set("PrimaryValueUId", primaryColumnValue);
						var args = {
							isSilent: true,
							messageTags: [this.sandbox.id]
						};
						this.sandbox.publish("SaveRecord", args, [this.sandbox.id]);
					} else {
						this.openCard(enums.CardStateV2.EDIT, typeColumnValue, primaryColumnValue);
					}
				},
 
				accountProductEntityListnerMsgHandler: function() {
					Terrasoft.ServerChannel.on(Terrasoft.EventName.ON_MESSAGE,
					function(scope, message){
							if (!message || message.Header.Sender !== "[AbAccountProductEntityEventListner]:[RequestToPlatform]:[Exception]") {
							return;
						}
						var message2 = message.Body;
						if (!this.Ext.isEmpty(message2)) {
							window.console.info(message2);
							this.Terrasoft.showInformation(message2);
						}
					}, this);
				}
			},
			diff: [
				{
					"operation": "merge",
					"name": "DataGrid",
					"values": {
						"className": "Terrasoft.ConfigurationGrid",
						"generator": "ConfigurationGridGenerator.generatePartial",
						"generateControlsConfig": { "bindTo": "generateActiveRowControlsConfig" },
						"changeRow": { "bindTo": "changeRow" },
						"unSelectRow": { "bindTo": "unSelectRow" },
						"onGridClick": { "bindTo": "onGridClick" },
						"activeRowActions": [
							{
								"className": "Terrasoft.Button",
								"style": this.Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
								"tag": "save",
								"markerValue": "save",
								"imageConfig": { "bindTo": "Resources.Images.SaveIcon" }
							},
							{
								"className": "Terrasoft.Button",
								"style": this.Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
								"tag": "card",
								"markerValue": "card",
								"imageConfig": { "bindTo": "Resources.Images.CardIcon" }
							},
							{
								"className": "Terrasoft.Button",
								"style": this.Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
								"tag": "cancel",
								"markerValue": "cancel",
								"imageConfig": { "bindTo": "Resources.Images.CancelIcon" }
							},
							{
								"className": "Terrasoft.Button",
								"style": this.Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
								"tag": "remove",
								"markerValue": "remove",
								"imageConfig": { "bindTo": "Resources.Images.RemoveIcon" }
							}
						],
						"initActiveRowKeyMap": { "bindTo": "initActiveRowKeyMap" },
						"activeRowAction": { "bindTo": "onActiveRowAction" },
						"multiSelect": false
					}
				}
			]
		};
	});

Пришлось переопределить editRecord():
 

var primaryColumnValue = typeof activeRow === "object" ? activeRow.get(activeRow.primaryColumnName) : activeRow;

т.к. дальше не срабатывало.
сейчас работает - http://prntscr.com/lfe61n
но при переходе на страницу редактирования поле для связи не заполняется - http://prntscr.com/lfe6k4
Подскажите в чем может быть дело?
Заранее благодарен.

У меня такой же вопрос

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

Попробуйте например вызывать openCardInChain и передавать туда значения по умолчанию
 

addChildRecord: function(typeColumnValue, date) {
var selectedItem = this.get("ActiveRow");
var defaultValues = [];
defaultValues.push({
	name: "ParentId",
	value: typeColumnValue
});
defaultValues.push({
	name: "UsrDate",
	value: date
});
var config = {
	sandbox: this.sandbox,
	schemaName: this.getEditPageSchemaName(typeColumnValue),
	operation: ConfigurationEnums.CardStateV2.ADD,
	moduleId: this.getChainCardModuleSandboxId(typeColumnValue),
	defaultValues: defaultValues
};
this.openCardInChain(config);
},

 

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

В разделе справочников есть с редактируемым реестром и карточкой, там всё работает; нужно посмотреть, как там сделали.

Попробуйте например вызывать openCardInChain и передавать туда значения по умолчанию
 

addChildRecord: function(typeColumnValue, date) {
var selectedItem = this.get("ActiveRow");
var defaultValues = [];
defaultValues.push({
	name: "ParentId",
	value: typeColumnValue
});
defaultValues.push({
	name: "UsrDate",
	value: date
});
var config = {
	sandbox: this.sandbox,
	schemaName: this.getEditPageSchemaName(typeColumnValue),
	operation: ConfigurationEnums.CardStateV2.ADD,
	moduleId: this.getChainCardModuleSandboxId(typeColumnValue),
	defaultValues: defaultValues
};
this.openCardInChain(config);
},

 

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

Версия 7.11.3. Sales Team

Кейс для воспроизведения:
1. в детали с редактируемым реестром открыть существующую запись на редактирование (действия детали - Изменить)
2. Закрыть карточку записи.
При этом в консоли отобразится ошибка "Элемент с ключом [object Object] Не существует "

Анализ ошибки  показал, что в базовой схеме BaseGridDetailV2 (метод getActiveRow в строка primaryColumnValue = this.get("ActiveRow")) в атрибуте ActiveRow содержится объект а не строка с идентификатором, т.о. данный метод отрабатывает с ошибкой при попытке определить выделенную строку в редактируемом реестре. 
Также выявлено, что объект присваивается атрибуту ActiveRow в методе restoreActiveRow (схема BaseGridDetailV2 ).

Когда будет исправлена эта ошибка?

У меня такой же вопрос

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

Игорь, добрый день!

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

Если у Вас есть точный кейс воспроизведения ошибки на чистой сборке, пожалуйста, опишите его нам, мы обязательно возьмем его в работу. Также мы можем рассмотреть данную ошибку на кастомной детали (для этого напишите нам на support@terrasoft.ru), но только при наличии оплаченного "Бизнес" или "Премиум" пакета поддержки, а также сертификата по разработке на платформе bpm’online уровня "Продвинутый".

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