Пытаюсь не давать людям закрывать задачи по определенным условиям. Всё хорошо до момента, пока не надо сделать это из esq.

Точнее, функция this.callParent(arguments) никак не работает из

esq.getEntity(Id, function(result) {
    this.callParent(arguments);
}, this);

Уже пробовал сделать var self = this и вызывать от self, пробовал сохранить arguments до esq. Ничего не помогает, задача не сохраняется. 

esq надо делать обязательно, т.к. изменение в другом объекте, которое я проверяю, может сделать другой человек и мне нужно проверить это прямо перед сохранением.

Есть способ?

Нравится

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

Добрый день, нужно либо смотреть в сторону asyncValidate (пример есть в DocumentPageV2), либо переопределить Save.

save: function(config,flag) {
    if (flag) {
        this.callParent(arguments);
    } else {
        //Validation Block
        Terrasoft.chain(
            this.checkPhonesCount,
            function (callback, scope) {
                this.save(config||{}, true),
                    callback.call(scope || this);
            },
            this
        );
    }

},
/**
 * Проверка количества телефонов
 * */
checkPhonesCount: function (callback, scope) {
    var leadId = this.get("Id");
    var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
        rootSchemaName: "UsrLeadPhone"
    });
    esq.addAggregationSchemaColumn("Id", Terrasoft.AggregationType.COUNT, "Count");

    esq.filters.addItem(Terrasoft.createColumnFilterWithParameter(
        Terrasoft.ComparisonType.EQUAL, "UsrLead", leadId));
    esq.filters.addItem(Terrasoft.createColumnFilterWithParameter(
        Terrasoft.ComparisonType.NOT_EQUAL, "UsrPhone", ""));
    esq.filters.addItem(Terrasoft.createColumnIsNotNullFilter("UsrPhone"));
    esq.getEntityCollection(function (response) {
        if (response && response.success) {
            var collection = response.collection;
            if (collection && collection.getCount() > 0) {
                var count = collection.getByIndex(0).get("Count");
                if (count >= 1) {
                    callback.call(scope || this);
                    return;
                }
            }
            var msg = this.get("Resources.Strings.PhonesErrorMessage");
            msg = this.Ext.String.format(msg, 1);
            Terrasoft.showInformation(msg);
        }
    }, this);
},

 

Я делаю так: 

1) у кнопки сохранить bind меняю на другую функцию (пр. onBeforeSave)

2) в onBeforeSave реализую логику, а дальше вызываю/не вызываю save-метод

Также можно в save зашить проверку какого-либо параметра. Сохранять arguments, проверять параметр, если false-> вызывать свою функцию, в конце своей функции параметр = true и вызвать save с  сохр. аргументами. Тоже в принципе вариант

Добрый день, нужно либо смотреть в сторону asyncValidate (пример есть в DocumentPageV2), либо переопределить Save.

save: function(config,flag) {
    if (flag) {
        this.callParent(arguments);
    } else {
        //Validation Block
        Terrasoft.chain(
            this.checkPhonesCount,
            function (callback, scope) {
                this.save(config||{}, true),
                    callback.call(scope || this);
            },
            this
        );
    }

},
/**
 * Проверка количества телефонов
 * */
checkPhonesCount: function (callback, scope) {
    var leadId = this.get("Id");
    var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
        rootSchemaName: "UsrLeadPhone"
    });
    esq.addAggregationSchemaColumn("Id", Terrasoft.AggregationType.COUNT, "Count");

    esq.filters.addItem(Terrasoft.createColumnFilterWithParameter(
        Terrasoft.ComparisonType.EQUAL, "UsrLead", leadId));
    esq.filters.addItem(Terrasoft.createColumnFilterWithParameter(
        Terrasoft.ComparisonType.NOT_EQUAL, "UsrPhone", ""));
    esq.filters.addItem(Terrasoft.createColumnIsNotNullFilter("UsrPhone"));
    esq.getEntityCollection(function (response) {
        if (response && response.success) {
            var collection = response.collection;
            if (collection && collection.getCount() > 0) {
                var count = collection.getByIndex(0).get("Count");
                if (count >= 1) {
                    callback.call(scope || this);
                    return;
                }
            }
            var msg = this.get("Resources.Strings.PhonesErrorMessage");
            msg = this.Ext.String.format(msg, 1);
            Terrasoft.showInformation(msg);
        }
    }, this);
},

 

Еще можно создать валидатор, который будет делать все проверки и срабатывать перед сохранением записи, его например привязать к полю "состояние"

Вообще, лучше не делать такие проверки только лишь в клиентской логике. Чисто теоретически, пользователь сможет отловить выполнение функции и в отладчике перешагнуть проверку. Хорошо бы и на объекте в обработчике Saving проверять соблюдение условия.

1. Если не вчитываться в смысл задачи, а только подсказать как сделать желаемое то вот этот способ:

save: function() {
   ...
   var args = arguments;
   var parentMethod = this.getParentMethod();
   ....
   esq.GetEntity(function() {
       parentMethod.apply(this, args)
   }, this);
}

2. По смыслу же задачи, вам нужно делать валидацию, а не переопределять методы сохранения. посмотрите примеры в коде с использованием методов addColumnValidator, validate, asyncValidate. 

addColumnValidator, validate делают синхронные проверки. asyncValidate асинхронная валидация, используется когда нужно сделать например запрос в БД для проверки.

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

Добрый всем день

Работаем над кастомным определением прав доступа (доступность полей в зависимости от роли по отношеню к контрагенту). Для этого в AccountLoaded проверяем у пользователя наличие роли по отношению к контрагенту (типа "индивидуальный менеджер", хранится в кастомном объекте, не суть), находим в VwSysEntitySchemaColumnRight доступные роли "индивидуальный менеджер"  поля Account, но они там хранятся только в виде SubjectColumnUId. Для самого же Account доступен список полей через Entity.GetColumnValueNames().

Возникло 2 вопроса:

1. Как эффективно получить список не администрируемых полей чтобы лишний раз их не проверять и не тащить методом исключения?

2. Как имея список SubjectColumnUId эффективно получить названия полей, чтобы скрыть те, на которые у роли нет прав? Через SysPackageSchemaDataColumn или как-то иначе?

 

Нравится

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

Можно ли из скрипта или правила динамически менять названия полей?

Например, называлось моё поле Цена, стало называться Стоимость. Я имею ввиду стандартными средствами, без html хаков?

Нравится

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

Добрый день, да можно, для этого при добавлении поля необходимо реализовать метод, который будет возвращать имя вашей колонки. И свойство Caption забиндить на него, или на какой-то атрибут (смысл тот же)

{

                "operation": "merge",

                "name": "Owner",

                "values": {

                    "caption": {

                        "bindTo": "getDetailCaption"

                    },

                    "layout": {

                        "colSpan": 12,

                        "rowSpan": 1,

                        "column": 12,

                        "row": 1

                    }

                }

            }

getDetailCaption: function() {

                var caption = this.get("Resources.Strings.GantDetailCaption");

                return caption;

            },

Добрый день, да можно, для этого при добавлении поля необходимо реализовать метод, который будет возвращать имя вашей колонки. И свойство Caption забиндить на него, или на какой-то атрибут (смысл тот же)

{

                "operation": "merge",

                "name": "Owner",

                "values": {

                    "caption": {

                        "bindTo": "getDetailCaption"

                    },

                    "layout": {

                        "colSpan": 12,

                        "rowSpan": 1,

                        "column": 12,

                        "row": 1

                    }

                }

            }

getDetailCaption: function() {

                var caption = this.get("Resources.Strings.GantDetailCaption");

                return caption;

            },

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

При установке пакета возникла ошибка:

"Не удалось загрузить файл на сервер"

Решение темы https://community.terrasoft.ru/questions/ustanovka-paketov-iz-prilozenia не помогло, в чем еще может быть проблема?

Нравится

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

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

Также см. похожие случаи.

Зверев Александр, ЛОГИ пустые, ни одной строчки!

 

Значит, логирование не настроено или смотрите не там. При каждом сбое должно писать в текстовые log-файлы стек вызова функций и прочее.

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

Столкнулся с проблемой. Велась разработка на одной базе, все отлично, но возникла необходимость перенести все на другую базу, при переносе пакета - схемы стают не редактируемые, отсюда вопрос: как перенести разработки и продолжить работу? 

Нравится

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

Вы можете через SQL сценарии или если есть доступ к SQL серверу выполнить запрос на разблокировку вашего пакета:

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

UPDATE [Название БД].[dbo].[SysPackage]
    SET InstallType = 0, [IsChanged] = 1, [IsLocked] = 1
    WHERE Name = 'Название пакета'

В некоторых случаях может потребоваться еще изменение значения Maintainer на Customer

 

Добрый день, вам через svn перенести бы изменения

Вы можете через SQL сценарии или если есть доступ к SQL серверу выполнить запрос на разблокировку вашего пакета:

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

UPDATE [Название БД].[dbo].[SysPackage]
    SET InstallType = 0, [IsChanged] = 1, [IsLocked] = 1
    WHERE Name = 'Название пакета'

В некоторых случаях может потребоваться еще изменение значения Maintainer на Customer

 

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

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

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

Единственным способом мне видится lookupListConfig filters. 

Вопрос - как корректно вызвать родительские фильтры, чтобы не копипастить их в свой код?

Нравится

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

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

Не так давно уже обсуждали подобную тему здесь.

Если бы родительские фильтры были вынесены в отдельный метод, тогда можно было бы просто Ваш метод унаследовать от родительского и в нём вызвать callParent.

Но так как, к сожалению, это не так, Вам прийдется дублировать родительские фильтры в своем коде sad

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

Не так давно уже обсуждали подобную тему здесь.

Если бы родительские фильтры были вынесены в отдельный метод, тогда можно было бы просто Ваш метод унаследовать от родительского и в нём вызвать callParent.

Но так как, к сожалению, это не так, Вам прийдется дублировать родительские фильтры в своем коде sad

Показать все комментарии
EmailContentBuilder
ckeditor
Шаблоны email сообщений
7.9
sales

Здравствуйте! Подскажите, как можно реализовать редактор шаблонов для текстовых сообщений(без html). Функционал как у email шаблонов но без изображений, html и прочих не текстовых элементов. Пробовали скопировать отдельно кнопку вставки макроса, а также пытались переделать сам редактор - была идея выключить html режим в ckeditor. Не разобрались как это реализовать, кнопку вставки макросов отдельно скопировать не удалось тк для нее необходимы параметры конфигурации и другие элементы которые зависят от редактора шаблонов email. Требуется только функционал вставки макросов (единственная кнопка из редактора). Текст сообщения допустимо размещать в обычном текстовом поле.

Нравится

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

В существующих дополнениях для отправки SMS есть редактор с макросами, но там в обоих названия полей вводятся вручную.

Либо же использовать дизайнер HTML-шаблонов, а при сохранении очищать текст от тегов, как при генерации темы обращения по письму.

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

1. Фильтрация лукапа такое же как и в обычной карточке?

Вот такой код:

"UsrLookup2": {
                lookupListConfig: {
                    filter: function() {
                        var filters = new Terrasoft.createFilterGroup();
                        filters.name = "CategoryFilter";
                        filters.logicalOperation = Terrasoft.core.enums.LogicalOperatorType.AND;
                        filters.isEnabled = true;
                        filters.addItem(Terrasoft.createColumnFilterWithParameter(
                            Terrasoft.ComparisonType.NOT_EQUAL, "МоеПоле", ""));
                        //filters.addItem(Terrasoft.createIsNotNullFilter("МоеПоле"));
                        return filters;
                    }
                }
            }

Не срабатывает - в окне выбора остаются записи которые должны были пропасть, кроме того в запросе к БД - нет такого фильтра

2. Можно ли по нажатии на кнопку прорисовать новое поле? нажимать можно неограниченное кол-во раз, создать много полей, задизейблить и потом откривать - не вариант

Нравится

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

Радчук Виталий Владимирович,

По фильтрации лукапа: строчку 

filters.logicalOperation = Terrasoft.core.enums.LogicalOperatorType.AND;
замените на

filters.logicalOperation = this.Terrasoft.LogicalOperatorType.AND;

И уберите вот эту строчку 

filters.isEnabled = true;

И ещё почитайте этот пост.

По второму вопросу смотрите статью на академии.

По фильтрации попробуйте вместо Вашего кода написать таким образом:

"UsrLookup2": {
                lookupListConfig: {
                    filter: function() {
                        var filters = new Terrasoft.createFilterGroup();
                        filters.logicalOperation = Terrasoft.core.enums.LogicalOperatorType.AND;
                        filters.isEnabled = true;
                        filters.add("CategoryFilter", Terrasoft.createColumnFilterWithParameter(
                            Terrasoft.ComparisonType.NOT_EQUAL, "МоеПоле", ""));
                        //filters.addItem(Terrasoft.createIsNotNullFilter("МоеПоле"));
                        return filters;
                    }
                }
            }

 

По второму вопросу посмотрите обсуждение здесь.

Алла Савельева,

По первому - не помогло. Еще заметил, что не могу запустить серверный код! ошибка 500, вот код: 

	var config1 = {
					serviceName: "ShowReport1CService",
					methodName: "CreateReport3",
					callback: function(response) {
						var result = response.CreateReport3Result;
					},
					data: {
					},
					scope: this,
					timeout: 1000000
				};
				ServiceHelper.callService(config1);

и на стороне сервера

[OperationContract]
		[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped,
		ResponseFormat = WebMessageFormat.Json)]
		public string CreateReport3()
		{
			return "asd";

В чем моя ошибка?

Радчук Виталий Владимирович,

По фильтрации лукапа: строчку 

filters.logicalOperation = Terrasoft.core.enums.LogicalOperatorType.AND;
замените на

filters.logicalOperation = this.Terrasoft.LogicalOperatorType.AND;

И уберите вот эту строчку 

filters.isEnabled = true;

И ещё почитайте этот пост.

По второму вопросу смотрите статью на академии.

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

Запускаем БП - в нем нужно прописать выгрузку FileStream или byte[] как обычный файл, чтобы после выполнения кода - началась загрузка файла

Нравится

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

Радчук Виталий Владимирович,

Можно.

onSalesDesktopV2: function() {
    var token = "CardModuleV2/UsrAwaitingPageV2";
    this.sandbox.publish("PushHistoryState", {hash: token});
}

 

Точно БП? В таком случае делать аналогично тому, как работает скачивание отчётов. Примерно:

1) Бп генерирует файл, складирует в IDataStore по определённому ключу (допустим генерируется guid). Далее из бп высылается сообщение на клиент с ключом.

2) Клиент принимает сообщение, снова обращается на сервер, но уже за скачиванием.

3) На сервере надо написать класс и функцию, которая будет возвращать стрим с дополнительными header-ами.

Всроде все. Можно вместо БП использовать сервис и тогда просто делать return ключа и не гемороиться с сообщениями.

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

тоесть нет простого пути(

БП мне нужен только для открития преднастроенной страницы, ее из клиента можно както открить?

Радчук Виталий Владимирович,

Можно.

onSalesDesktopV2: function() {
    var token = "CardModuleV2/UsrAwaitingPageV2";
    this.sandbox.publish("PushHistoryState", {hash: token});
}

 

Пащенко Александр Сергеевич,

Дошло руки до этого, хочу убрать бп и вызвать страницу из кода.

"CardModuleV2/UsrAwaitingPageV2" - это точно так как нужно? 

UsrAwaitingPageV2 - название страницы? То что пишет в define.

CardModuleV2 - остается.

Пишет множество ошибок:

Заголовок для подписи "LOOKUPfa02a572-e764-48bf-ad0b-4997972a368f" не был найден.

Невозможно найти колонку по конфигурации: "{"layout":{"colSpan":12,"rowSpan":1,"column":12,"row":1,"layoutName":"Header"},"bindTo":"UsrLookup2","enabled":true,"contentType":5,"name":"LOOKUPfa02a572-e764-48bf-ad0b-4997972a368f"}" .

Uncaught TypeError: Cannot read property 'header' of undefined
    at i.getPageHeader (:82/0/conf/content/BasePageProcessTemplate.js?hash=9dd7bbf4b00441f59c94ee1b3eae3f45:95)
    at initHeader (:82/0/conf/content/BasePageV2.js?hash=9dd7bbf4b00441f59c94ee1b3eae3f45:2345)
    at i.onEntityInitialized (:82/0/conf/content/BasePageV2.js?hash=9dd7bbf4b00441f59c94ee1b3eae3f45:1680)
    at i.callParent (all-combined.js:6)
    at i.onEntityInitialized (:82/0/conf/content/BasePageV2.js?hash=9dd7bbf4b00441f59c94ee1b3eae3f45:3378)
    at i.callParent (all-combined.js:6)
    at i.onEntityInitialized (:82/0/conf/content/BasePageV2.js?hash=9dd7bbf4b00441f59c94ee1b3eae3f45:3565)
    at Object.callback (all-combined.js:6)
    at i.<anonymous> (all-combined.js:7)
    at Object.Terrasoft.eachAsync (all-combined.js:7)

file: http://192.168.10.24:82/0/conf/content/BasePageProcessTemplate.js?hash=9dd7bbf4b00441f59c94ee1b3eae3f45
 line: 95
 column: 24
 message: Uncaught TypeError: Cannot read property 'header' of undefined 
 date: Fri Dec 07 2018 20:17:33 GMT+0300 (Москва, стандартное время)
 stack: TypeError: Cannot read property 'header' of undefined
    at i.getPageHeader (http://192.168.10.24:82/0/conf/content/BasePageProcessTemplate.js?hash=9dd7bbf4b00441f59c94ee1b3eae3f45:95:24)
    at initHeader (http://192.168.10.24:82/0/conf/content/BasePageV2.js?hash=9dd7bbf4b00441f59c94ee1b3eae3f45:2345:85)
    at i.onEntityInitialized (http://192.168.10.24:82/0/conf/content/BasePageV2.js?hash=9dd7bbf4b00441f59c94ee1b3eae3f45:1680:10)
    at i.callParent (http://192.168.10.24:82/core/88fb020650912ad22d23339c297888ad/combined/all-combined.js:6:44657)
    at i.onEntityInitialized (http://192.168.10.24:82/0/conf/content/BasePageV2.js?hash=9dd7bbf4b00441f59c94ee1b3eae3f45:3378:10)
    at i.callParent (http://192.168.10.24:82/core/88fb020650912ad22d23339c297888ad/combined/all-combined.js:6:44657)
    at i.onEntityInitialized (http://192.168.10.24:82/0/conf/content/BasePageV2.js?hash=9dd7bbf4b00441f59c94ee1b3eae3f45:3565:10)
    at Object.callback (http://192.168.10.24:82/core/88fb020650912ad22d23339c297888ad/combined/all-combined.js:6:73147)
    at i.<anonymous> (http://192.168.10.24:82/core/88fb020650912ad22d23339c297888ad/combined/all-combined.js:7:1024268)
    at Object.Terrasoft.eachAsync (http://192.168.10.24:82/core/88fb020650912ad22d23339c297888ad/combined/all-combined.js:7:156660)

 

Показать все комментарии
FileDetailV2
sales
javascript
details

Добрый день! 

Задача: создать произвольную деталь "файлы и ссылки", с возможностью группирования добавляемых файлов по значению (колонке). 

Данную задачу я решил разбить на две, первая есть добавление самой детали(1), вторая уже реализация группирования(2).

1.

1.1 Для добавления детали я добавил "схема модели представления детали с реестром".

1.2 Унаследовал ее от "FileDetailV2 ( UIv2 )".

1.3 Добавил следующий код: 

define("UsrDocumentsFileDetail", [],
    function() {
		return {
			entitySchemaName: "UsrDocumentsListImage"
		};
	}
);

1.4 Затем я добавил объект "UsrDocumentsListImage" унаследовав его от "Файл ( Base )".

В объект добавил Lookup на форму, на которой будет отображаться создаваемая деталь. Подробная структура объекта:

[Id],
[CreatedOn],
[CreatedById],
[ModifiedOn],
[ModifiedById],
[Name],
[Notes],
[LockedById],
[LockedOn],
[Data],
[TypeId],
[Version],
[Size],
[ProcessListeners],
[UsrApplicationFormId] -- Lookup на форму для отображения детали

1.5 На модель страницы формы я добавил следующий код: 

details: {
    // Настройка детали [(Просмотр изображений)Документы]
    "UsrDocumenctImageViewDetailElement": {
	    "schemaName": "UsrDocumentsFileDetail",
	    "filter": {
		    "detailColumn": "UsrApplicationForm",
		    "masterColumn": "Id"
    	}
    }
},
diff: [
    {
        {
			"operation": "insert",
			// Название детали.
			"name": "UsrDocumenctImageViewDetailElement",
			"values": {
				"itemType": Terrasoft.core.enums.ViewItemType.DETAIL,
				"markerValue": "added-detail"
			},
			// Контейнеры, в котором размещена деталь.
			// Деталь размещена на вкладке [ДОКУМЕНТЫ И ФОТО].
			"parentName": "Tabd3595bedTabLabel",
			"propertyName": "items",
			// Индекс в списке добавляемых элементов.
			"index": 1
		}
    }
]

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

Лог консоли браузера: 

Error while sending request 
	response status: 500 (ItemNotFoundException)
	request url: ../DataService/json/SyncReply/SelectQuery
	method: POST
	request data: {"rootSchemaName":"UsrDocumentsListImage","operationType":0,"filters":{"items":{"211c1207-255e-48c2-8eb6-e011b92fdfc6":{"filterType":1,"comparisonType"...

Uncaught i {message: "Элемент коллекции с именем UsrDocumentsListImage не найден"}

user: Supervisor/7f3b869f-34f3-4f20-ab4d-7480a5fdf647
 file: http://localhost:83/0/configuration/d79cf7d52ccb236d2d57879ca34250e6ru-RU/FileDetailV2.js
 line: 183
 column: 7
 message: Uncaught Terrasoft.UnknownException: Элемент коллекции с именем UsrDocumentsListImage не найден 
 date: Mon Nov 12 2018 17:05:55 GMT+0300 (Москва, стандартное время)
 stack: undefined

Вопрос: 

Как исправить данную проблему и что означает данная ошибка? 

Нравится

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

Добрый день, а в таблице все поля корректно заполняются?

Попробуйте в объекте UsrDocumentsListImage переименовать поле UsrApplicationForm на UsrDocumentsListImage, возможно дело кроется в методе initParentEntity 

Колодяжный Владислав Эдуардович,

Спасибо за Ваш ответ! 

Заполняется все кроме  lockedById([uniqueidentifier] NULL) и lockedOn([datetime2](7) NULL). 

В случае переименования в объекте UsrDocumentsListImage поля UsrApplicationForm на UsrDocumentsListImage компилятор ругается:

Элемент c идентификатором "UsrDocumentsListImage" уже существует

Может, набор и имена полей в объекте и в select-запросе отличаются. Посмотрите в Fiddler-е наполнение request data полностью.

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