Вопрос

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

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

Ответ

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

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 комментариев
Показать все комментарии
Публикация
//Добавляем в методы
methods: {
    //TODO: Изначальная инициализация
    tabRender: function(tabObject) {
        //TODO
    },
    subscribeForEvents: function() {
        this.on("change:UsrType", this.changeTabsVisibility.bind(this)); //UsrType - поле, по которому будут скрываться вкладки
    },
    changeTabsVisibility: function() {
        var usrType = this.get("UsrType") || {}; //"UsrType" - поле, по которому будут скрываться вкладки
        switch(usrType.value) {
            case "933b3812-4882-484f-9ba7-37b272443f36": //id одного из состояний из поля UsrType
                this.hideTabByName( "Tab98e9ceedTabLabel", true ); //Имя нужной вкладки, в diff выглядит так "name": "Tab98e9ceedTabLabel",
                this.hideTabByName( "Tabc65f2ae2TabLabel", true ); //Имя нужной вкладки. Та, что true будет скрыта
                this.hideTabByName( "Tabfcd67f08TabLabel", false ); //Имя нужной вкладки. Та, что false будет отображаться
                break;
            case "49bbaa75-dfdd-4de5-a2fa-4d9b2ba54b96": //id одного из состояний из поля UsrType
                case "8daf0d76-5522-4444-843d-54f05bae3ad9": //id одного из состояний из поля UsrType
                    this.hideTabByName( "Tabfcd67f08TabLabel", true ); //Имя нужной вкладки
                    this.hideTabByName( "Tabc65f2ae2TabLabel", true ); //Имя нужной вкладки
                    this.hideTabByName( "Tab98e9ceedTabLabel", false ); //Имя нужной вкладки
                    break;
                case "b74416cd-ae95-4e6c-b7f9-fc80dcbcf7af": //id одного из состояний из поля UsrType
                    this.hideTabByName( "Tabfcd67f08TabLabel", true ); //Имя нужной вкладки
                    this.hideTabByName( "Tab98e9ceedTabLabel", true ); //Имя нужной вкладки
                    this.hideTabByName( "Tabc65f2ae2TabLabel", false ); //Имя нужной вкладки
                    break;
                default: //Если состояние не указано
                    this.hideTabByName( "Tabfcd67f08TabLabel", false ); //Имя нужной вкладки
                    this.hideTabByName( "Tab98e9ceedTabLabel", false ); //Имя нужной вкладки
                    this.hideTabByName( "Tabc65f2ae2TabLabel", false ); //Имя нужной вкладки
        }
    },
    init: function() {
        this.callParent(arguments);
        this.subscribeForEvents();
    },
    hideTabByName: function(tabName, isHide){
        var tabsCollection = this.get("TabsCollection");
        if(tabsCollection){
            var tabIndex = tabsCollection.collection.keys.indexOf(tabName);
            var tabsPanelDomElement = document.getElementById("ActivityPageV2TabsTabPanel-tabpanel-items"); // Вместо "ActivityPageV2..." в этой строке подставьте своё)
            if(tabsPanelDomElement){
                tabDomElement = tabsPanelDomElement.querySelector('[data-item-index="'+tabIndex.toString()+'"]');
                if(tabDomElement){
                    if(isHide){
                        tabDomElement.style.display = "none";
                    }else{
                        tabDomElement.style.display = null;
                    }
                }
            }    
        }
    }
},

 

Нравится

Поделиться

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 комментариев
Показать все комментарии

Вопрос

Установила в мобильном приложении Automatic Synchronization – Only through Wifi. Скажите, с какой периодичностью запускатся автоматическая синхронизация данных?

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

Ответ

Каждый раз при сворачивании приложения синхронизация происходит через 30 сек. И если пользователь активирует снова приложение эта синхронизация останавливается.

Примечание. Из-за специфики операционной системы на Iphone, может останавливать все процессы в фоне приблизительно через 3 минуты. Т.е. если синхронизация не успела завершится в фоне – то она по факту не прошла. 

Нравится

Поделиться

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