Вопрос

Как добавить кнопку в коммуникационную панель?

Ответ

  1. Заместить модуль «CommunicationPanel» в котором будет описана новая кнопка.
define("CommunicationPanel", ["terrasoft", "CommunicationPanelHelper"],
	function(Terrasoft, CommunicationPanelHelper) {
		return {
			messages: {
				"SelectCommunicationPanelItem": {
					"mode": Terrasoft.MessageMode.PTP,
					"direction": Terrasoft.MessageDirectionType.SUBSCRIBE
				}
			},
			attributes: {
				"UsrMyMenuActive": {
					"dataValueType": Terrasoft.DataValueType.BOOLEAN,
					"type": Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
					"value": false
				},
				"UsrMyMenuCounter": {
					"dataValueType": Terrasoft.DataValueType.TEXT,
					"type": Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
					"value": ""
				},
				"UsrMyMenuVisible": {
					"dataValueType": Terrasoft.DataValueType.BOOLEAN,
					"type": Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
					"value": true
				}
			},
			methods: {
				getPanelItemConfig: function(moduleName) {
					var config = this.callParent(arguments);
					if (moduleName !== "UsrMyMenuModule") {
						return config;
					}
					return Ext.apply(config, {
						keepAlive: false
					});
				},
				selectItem: function(config) {
					this.set("SelectedMenuItem", config.selectedItem);
				},
				getUsrMyMenuImageConfig: function(itemTag) {
					return this.get("Resources.Images.VisaMenuIcon");
				},
				getUsrMyMenuCaption: function(itemTag) {
					return "test";
				}
			},
			diff: [
				{
					"operation": "insert",
					"index": 0,
					"parentName": "communicationPanelContent",
					"propertyName": "items",
					"name": "usrMyMenu",
					"values": {
						"tag": "UsrMyMenu",
						"visible": {"bindTo": "UsrMyMenuVisible"},
						"imageConfig": {"bindTo": "getUsrMyMenuImageConfig"},
						"caption": {"bindTo": "getUsrMyMenuCaption"},
						"generator": "CommunicationPanelHelper.generateMenuItem"
					}
				}
			]
		};
	});
  1. Создать модуль панели, в модуле должны быть обязательные сообщения, как и в ESNFeedModule:

RerenderModule – подписка, адресное.

InitModuleViewModel – подписка, адресное.

define("UsrMyMenuModule", [], function() {
	Ext.define("Terrasoft.configuration.UsrMyMenuModule", {
 
		extend: "Terrasoft.BaseSchemaModule",
		alternateClassName: "Terrasoft.UsrMyMenuModule",
 
		generateViewContainerId: false,
 
		initSchemaName: function() {
			this.schemaName = "UsrMyMenu";
		},
 
		initHistoryState: Terrasoft.emptyFn,
 
		init: function() {
			this.callParent(arguments);
			this.initMessages();
		},
 
		initMessages: function() {
			this.sandbox.subscribe("RerenderModule", function(config) {
				if (this.viewModel) {
					this.render(this.Ext.get(config.renderTo));
					return true;
				}
			}, this, [this.sandbox.id]);
		},
 
		createViewModel: function() {
			var viewModel = this.callParent(arguments);
			return viewModel;
		}
 
	});
	return Terrasoft.UsrMyMenuModule;
});

3. Создать схему представления карточки

define("UsrMyMenu", [], function() {
		return {
			mixins: {
			},
			messages: {
			},
			attributes: {
			},
			methods: {
				init: function(callback, scope) {
					this.callParent([function() {
						callback.call(scope);
					}, this]);
				},
				onTestClick: function() {
					alert(1);
				}
			},
			diff: [
				//MyMenu
				{
					"operation": "insert",
					"name": "MyMenu",
					"propertyName": "items",
					"values": {
						"generateId": false,
						"itemType": Terrasoft.ViewItemType.CONTAINER,
						"items": []
					}
				},
				//ShowNewMessagesButton
				{
					"operation": "insert",
					"name": "ShowNewMessagesButton",
					"parentName": "MyMenu",
					"propertyName": "items",
					"values": {
						"generateId": false,
						"itemType": Terrasoft.ViewItemType.BUTTON,
						"caption": "Test!",
						"click": {bindTo: "onTestClick"}
					}
				}
			]
		};
	});

Результат:

Изображение удалено.

Нравится

Поделиться

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

Вопрос

Как сделать, чтобы колонка была ссылочной? Например, колонка "Контрагент" в разделе "Контакт".

Ответ

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

Пример реализации, можете посмотреть в MobileContactModuleConfig (раздел «Контакты»):

Terrasoft.sdk.RecordPage.configureColumn("Contact", "primaryColumnSet", "Account", {
    viewType: Terrasoft.ViewTypes.Preview
});
 

Нравится

Поделиться

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

Вопрос

Что можно сделать, чтобы отсортировать список договоров по возрастанию или убыванию номеров, а не так, как на скрине?

Изображение удалено.

Ответ

Данное поведение сортировки обусловлено тем, что поле [Номер] - текстовое, а правила сортировки текста отличаются от правил сортировки чисел. Для решения задачи сортировки, необходимо:

1. Создать замещающий объект [Договор] и добавить в него новую числовую колонку. Опубликовать объект.

Изображение удалено.

2. Открыть замещающий объект [Договор] вновь, создать событие [Перед сохранением записи] ([ContractSaving]), перейти к процессу объекта ([Дополнительно] – [Открыть процесс]).

Изображение удалено.

3. В процессе добавить [Событийный подпроцесс].

4. На подпроцессе разместить сигнал, в поведении сигнала указать сигнал - [ContractSaving].

5. За сигналом добавить скрипт-задачу с кодом:

int num = 0;
bool res = int.TryParse(Entity.Number, out num);
if (res == true)
{
    Entity.UsrNumber = num;
}
return true;

6. За скрипт-задачей разместить завершающий сигнал. Сохранить. Опубликовать процесс.

Изображение удалено.

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

Изображение удалено.

Для обновления всех старых записей системы и заполнения новой колонки значениями, в конфигурации необходимо добавить на закладке [SQL-сценарии] скрипт и выполнить его:

UPDATE Contract
SET UsrNumber = CONVERT(INT, Number)

Все это справедливо, если в поле номер пишутся номера без префикса.

Нравится

Поделиться

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

Вопрос

Как быстро сгенерировать код страницы для мобильного приложения

Можно использовать для:

  • Edit
  • Grid
  • Preview

Ответ

Выполнять в консоли браузера эмулятора 

(new Terrasoft.CodeGeneration.PageCodeGenerator({
    modelName: "Contact", 
    pageType: Terrasoft.PageTypes.Edit
})).generate()

В modelName указываем нужный объект

В pageType  указываем тип страницы: 

pageType: Terrasoft.PageTypes.Grid
pageType: Terrasoft.PageTypes.Edit
pageType: Terrasoft.PageTypes.Preview

Изображение удалено.

В итоге получается:

Terrasoft.LastLoadedPageData = {
    controllerName: "Terrasoft.configuration.ContactEditPageController",
    viewXClass: "Terrasoft.configuration.ContactEditPageView"
};
 
Ext.define("Terrasoft.configuration.view.ContactEditPage", {
    extend: "Terrasoft.view.BaseEditPage",
    alternateClassName: "Terrasoft.configuration.ContactEditPageView",
    config: {
        id: "ContactEditPage"
    }
});
 
Ext.define("Terrasoft.configuration.controller.ContactEditPage", {
    extend: "Terrasoft.controller.BaseEditPage",
    alternateClassName: "Terrasoft.configuration.ContactEditPageController",
    statics: {
        Model: Contact
    },
    config: {
        refs: {
            view: "#ContactEditPage"
        }
    }
});

 

Нравится

Поделиться

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

Задача

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

Решение

Необходимо заменить метод PrepareEmployeeEditFilter схемы UserEditPage на следующий:

var filters = e.Filters;
filters.Add(new Dictionary<string, object> {
    {"comparisonType", FilterComparisonType.Equal},
    {"leftExpressionColumnPath", "[SysAdminUnit:Contact].Id"},
    {"aggregationType", AggregationTypeStrict.Count},
    {"useDisplayValue", false},
    {"rightExpressionParameterValues", new object[] {0}}});
filters.Add(new Dictionary<string, object> {
    {"comparisonType", FilterComparisonType.Equal},
    {"leftExpressionColumnPath", "Account.Type"},
    {"useDisplayValue", false},
    {"rightExpressionParameterValues", new object[] { new Guid("57412fad-53e6-df11-971b-001d60e938c6")}}});
e.ParametersValue.Add("hideButtons", true);

Где "57412fad-53e6-df11-971b-001d60e938c6" - айди таблицы AccountType соответствующий значению "Наша компания".

Необходимые условия

Для версии 7.4

Нравится

Поделиться

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

Симптомы

Bug mobile report:

Type: Terrasoft.SyncException 

Message: В процессе синхронизации произошла ошибка 

Stack trace: 



Type: Terrasoft.FileException 

Message: В процессе записи в файл произошла ошибка 

AdditionalInfo: Имя: BPMonline700/Downloads/6005bfc5-5ea7-42da-82e6-15f5f4c9e80a/счет на оплату #6.pdf

Type: Terrasoft.FileSystemException 

Message: undefined 

AdditionalInfo: Код: undefined 

Data: 4 

Model Name: iPhone8,2 (0x0)

Platform: iOS

Platform Version: 9.2.1

IsOnlineMode: false

UIVersion: 2

ApplicationVersion: 7.7.8

ApplicationMajorVersion: 7.7

ContactId: c41b4784-a414-438c-a846-c5bf418f0056

CultureName: ru-RU

ApplicationRevision: 0

BackgroundSyncMode: 3

WorkplaceCode: DefaultWorkplace

Причина

Данная ошибка возникает из-за того, что в приложении присутствует файл «счет на оплату #6.pdf» (деталь «Файлы и ссылки»), в котором есть спецсимвол «#». В мобильном устройстве на платформе iOS есть ограничения по использованию спецсимволов при передаче запросов/файлов.

Решение

Для исправления необходимо переименовать файл и убрать символ «#». Это можно сделать, например, следующими способами:

- найти прикрепленный файл вручную открывая каждую запись в приложении;

- по ID записи (например, «6005bfc5-5ea7-42da-82e6-15f5f4c9e80a») в БД найти родительский объект, чтобы понять в каком разделе и в какой записи находиться данный файл и также переименовать через БД или на уровне приложения. Для упрощения поиска прикрепил скрипт, который можно выполнить на уровне БД и определить в каком объекте находиться данный файл.  

-- Вхідні параметри - назва та значення стовпчика:
DECLARE @COLUMN_NAME NVarChar(100) = 'Id'
DECLARE @COLUMN_VALUE NVarChar(100) = '6005bfc5-5ea7-42da-82e6-15f5f4c9e80a'
DECLARE @tableName VARCHAR(50)
DECLARE tablesCursor CURSOR LOCAL FORWARD_ONLY STATIC FOR
    -- Запит повертає імена таблиць в БД, у яких є стовпчик @COLUMN_VALUE:
    SELECT table_name = sysobjects.name
    FROM sysobjects
    JOIN syscolumns ON sysobjects.id = syscolumns.id         
    WHERE sysobjects.xtype='U'
    and syscolumns.name = @COLUMN_NAME
OPEN tablesCursor
FETCH NEXT FROM tablesCursor INTO @tableName
WHILE @@FETCH_STATUS = 0
BEGIN  
    -- Якщо в якійсь таблиці є стопчик @COLUMN_NAME зі значенням @COLUMN_VALUE -
    -- вивести ім'я таблиці, запит і кількість рядків у запиті
    EXEC ('DECLARE @recordCount INT;
        DECLARE @quotesChar CHAR = char(39);
        DECLARE @tabChar CHAR = char(9);
        BEGIN TRY
            SET @recordCount =
                (SELECT COUNT(*)
                FROM [' + @tableName + '] where ' + @COLUMN_NAME + ' = ''' + @COLUMN_VALUE + ''')
                IF @recordCount > 0
                    BEGIN                                                 
                        PRINT ''''
                        PRINT ''-- ' + @tableName + ':''
                        PRINT ''     SELECT * FROM ' + @tableName +
                            ' WHERE ' + @COLUMN_NAME +
                            ' = '' + @quotesChar + ''' + @COLUMN_VALUE + ''' + @quotesChar + ''''                                          
                        PRINT ''     -- Кількість рядків у запиті: '' + CAST(@recordCount as VARCHAR(5))
                    END
        END TRY        
        BEGIN CATCH                                   
        END CATCH;                      
    ');
    FETCH NEXT FROM tablesCursor INTO @tableName
END
CLOSE tablesCursor
DEALLOCATE tablesCursor

Необходимые условия и возможные ограничения

Данная ошибка актуальна для iOS (iPhone)

Нравится

Поделиться

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

Вопрос

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

Ответ

Каждый объект имеет таблицу прав имеющую следующее имя Sys + объект + Right, (для обращения это будет SySCaseRight),в данную таблицу заносятся права с указанием SySAdminUnitId - идентификатор записи SySAdminUnit(таблица пользователей и групп). Таблица содержит поле RecorId - id записи к которой применяются права, Operation - операцию на которую выдаются права и RightLevel - уровень прав.

В SourceId находится Id из таблицы SysEntitySchemaRecRightSource, это источник раздавший права(Владелец, автор, Default)

Значения для RightLevel:

      0 - Deny

      1 - CanRead

      2 - CanEdit

Значения для Operation:

      0 - Чтение

      1 - Изменение

      2 - Удаление

Нравится

Поделиться

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

Симптомы

Не работает "Перейти к справке" ("Online help"). При переходе ошибка:

Изображение удалено.

Например, воспроизведется если переходит к продукту Customer Engagement Centre, который в 7.7., который уже называется просто Customer Centre, поэтому справку и не находит.

Причина

Некорретно прописаны системные настройки "Редакция продукта" ("Product") или "Версия конфигурации" ("Configuration version").

Решение

Для решения необходимо поменять значение в системной настройке «Product» (прописать корректное название используемого продукта).

Изображение удалено.

И убедиться, что в системной настройке «Configuration version» проставлено значение «7.7.0».

Изображение удалено.

Нравится

Поделиться

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

Вопрос

Как поменять местами кнопки? 

Изображение удалено.

Ответ

Данное расположение с версии 7.8 изначально было задумано из-за того, что пользователь случайно («автоматически») удаляет запись.

В данном случае пользователь немного задумается, что именно он нажимает.

Данная функциональность реализована в схеме «GridUtilitiesV2» (пакет «NUI»). Метод называется «checkCanDeleteCallback».

Изображение удалено.Если Вы хотите поменять местами кнопки, то Вам необходимо заместить «BaseSectionV2» и скопировать метод «checkCanDeleteCallback» и поменять местами «Terrasoft.MessageBoxButtons.NO.returnCode» и «Terrasoft.MessageBoxButtons.YES.returnCode».

Нравится

Поделиться

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

Вопрос

Как добавить кнопку в реестр детали для активной строки?

Ответ

Можно реализовать следующим образом:

В скрипте детали в блок diff добавить дополнительные свойства для DataGrid (название и заголовок кнопки приведены в качестве примера):

{
        "operation": "merge",
        "name": "DataGrid",
        "values": {
                "activeRowAction": {"bindTo": "onActiveRowAction"},
                "activeRowActions": [
                        {
                                "className": "Terrasoft.Button",
                                "style":this.Terrasoft.controls.ButtonEnums.style.BLUE,
                                "markerValue": "myButtonAction",
                                "tag": "myAction",
                                "caption": "MyButton"
                        }
                ]
        }
}

После этого при выделении активной строки в детали должна появиться синяя кнопка с заголовком MyButton.

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

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

methods: {
        onActiveRowAction: function(buttonTag, primaryColumnValue) {
                if (buttonTag === "myAction") {
                        // весь код ниже можно убрать, он демонстрирует, что значения
                        // primaryColumnValue и activeRowId равны
                        var activeRow = this.getActiveRow();
                        var activeRowId = activeRow.get("Id");
                        console.log(primaryColumnValue);
                        console.log(activeRowId);
                        // дальше Ваша реализация
                        ...
                }
        },
        ...
}

 

Нравится

Поделиться

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