Готовлюсь к переносу пакета через SVN и смущает один момент.

У меня созданы новые детали. Пусть сами схемы он перенесет, а вот записи таблиц SysDetail (по 1 на деталь), SysSchema, возможно какие-то другие - что с ними будет?

Ведь без этих записей система нормально работать не будет?!

Нравится

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

Здравствуйте, Алексей!

 

Для переноса содержимого некоторых таблиц используется механизм привязки данных к пакету - https://academy.terrasoft.ru/documents/technic-sdkmp/7-11/privyazka-dan…

 

Для упрощения привязки можно воспользоваться бесплатным дополнением с Marketplace - https://marketplace.terrasoft.ru/app/data-binding-tool

Привет!

А детали создавались мастером? Если да, то почти все привязки автоматом создаются в пакете Custom. Все, что надо сделать - "повторить" эти привязки в своем пакете.

Например, может быть создана привязка следующего вида "SysDetail_DetailManager_d95ebba0c04a454fad3bbb45962eef2d" по объекту SysDetail.

В этом случае надо действовать примерно по следующему плану:

1. открыть привязку и внимательно на нее взглянуть (можно для надежности сделать скриншот)

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

3. выбрать свой пакет и создать привязку по нужному объекту (в данном примере SysDetail, который в выпадашке объектов называется Details lookup)

4. обязательно выбрать тип установки как Installation

5. обязательно отфильтровать по Id. Этот идентификатор есть в названии привязки, но его надо привести к правильному виду GUID. Например, d95ebba0c04a454fad3bbb45962eef2d должен превратиться в d95ebba0-c04a-454f-ad3b-bb45962eef2d

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

7. сохранить и вкоммитить

 

P.S. Я не знаю, как работает утилита выше, которую посоветовал Павел, но подозреваю, что уже созданные привязки в других пакетах эта утилита не удаляет и их надо будет зачищать вручную.

 

Кстати, надо еще не забыть привязать настройку колонок детали... в описании утилиты сказано, что она позволяет привязывать к пакету настройку колонок по секциям, и ничего не сказано про детали. Если настройка колонок не задана в явном виде в секции diff cхемы детали и настройка колонок делалась через интерфейс, то надо будет привязывать еще и профиль отображения. Это объект SysProfileData (в выпадашке User profile) с фильтрацией по содержимому поля Key. Это поле должно содержать название детали или секции и, возможно еще содержать текст "GridSettings". Также, если не задан контакт у записи, то это отображение для всех - т.е. дефолтное отображение, если пользователь себе ничего не настраивал.

Максим Цынгаев,

не понял про SysProfileData. Как сделать эту привязку?

Алексей-Карягин,

Давай на примере покажу.

Есть собственная секция OpportunityPaymentsSection. Я настроил отображение колонок и сохранил, причем сохранял как для Supervisor, так и для All. Чтобы привязать это отображение к пакету, я создал привязку на вкладке Data по объекту User profile (SysProfileData - это так называется объект в БД и есть соответствующая таблица) и отфильтровал по двум критериям:

1. Key содержит название схемы секции

2. Contact не заполнен (т.е. в базе NULL)

Вот так это выглядит в интерфейсе:

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

Добрый день.

Запускаю  БП из действия раздела:

var selectedRows = this.get("SelectedRows");
var accounts = selectedRows.join();
var processName = "UsrChangeAccountOwnerProcess";
 
var params = {
	AccountIds: accounts
};
ProcessModuleUtilities.runProcess(processName, params);



При запуске БП по выделенным записям (более 50 записей) возвращается ошибка:

https://yadi.sk/i/k7KXj5VE3PTDoj

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

Вопросы:

Как снять ограничение на длину параметра?

Можно ли запустить БП с использованием callService, передав параметры в виде jsonData, а не в url?

Нравится

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

Добрый день. Передать параметры в виде JSON строки, к сожалению, не выйдет. Вам стоит смотреть в сторону передачи фильтров, по которым можно будет выбрать данные записи. Пример можно глянуть в реализации мультиделита. Серверный код дисериализации находится в GridUtilitiesService DeleteRecordsAsync.

Терещук Сергей,

А с чем связана описанная мной проблема?

Коновалов Игорь,

Я думаю, что это вызвано ограничениями, которые прописаны для WCF сервиса, который вызывается. В частности, 

maxReceivedMessageSize. Но я могу и ошибаться.

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

Всем доброго времени суток. Версия 7.10.

На странице активностей есть маленький фильтр поиска по участникам Активности.

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

Я хочу его немного переделать, чтобы в появляющемся по клику на него окне справочника были доступны только контакты, указанные как сотрудники в колонке тип, вместо того Terrasoft.createColumnIsNotNullFilter('[SysAdminUnit:Contact].Id'), который там сейчас стоит. Насколько я понимаю, свойства этого блока указываются внутри функции initFixedFiltersConfig в схеме ActivitySectionV2. Переопределил схему, и заменил функцию, где указал вот такое свойство:

{
	name: "Owner",
	caption: this.get("Resources.Strings.OwnerFilterCaption"),
	addOwnerCaption: this.get("Resources.Strings.AddEmployeeFilterCaption"),
	hint: this.get("Resources.Strings.SelectEmployeeFilterHint"),
	columnName: "Owner",
	defValue: this.Terrasoft.SysValue.CURRENT_USER_CONTACT, //
	dataValueType: this.Terrasoft.DataValueType.LOOKUP,
	filters: [
		function() {
			var filterGroup = Ext.create("Terrasoft.FilterGroup");
			filterGroup.add("OnlyCustomers",
				this.Terrasoft.createColumnFilterWithParameter(
				this.Terrasoft.ComparisonType.EQUAL,
				"Type",
				"60733efc-f36b-1410-a883-16d83cab0980"));
			return filterGroup;
		}
	],
	appendFilter: function(filterInfo) {
		/.../
	}
}

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

 

Нравится

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

Здравствуйте Денис,

Да, изменения нужно было вносить в initFixedFiltersConfig метод, но замещать у фильтра свойство "filter", проставив в него кстомный метод, который возвращает фильтр нужного вида.



Изменения отличные от оригинального initFixedFiltersConfig:



результат:

Вся замещающая схема:

define("ActivitySectionV2", ["terrasoft", "ConfigurationConstants"],
	function(Terrasoft, ConfigurationConstants) {
		return {
			entitySchemaName: "Activity",
			messages: {
			},
			mixins: {
			},
			attributes: {
			},
			methods: {
				initFixedFiltersConfig: function() {
 
					var filterGroup = Ext.create("Terrasoft.FilterGroup");
					filterGroup.add("OnlyCustomers",
						this.Terrasoft.createColumnFilterWithParameter(
						this.Terrasoft.ComparisonType.EQUAL,
						"Type",
						"60733efc-f36b-1410-a883-16d83cab0980"));
 
					var myOwnerFilter = function OwnerFilter() {
						return filterGroup;
					};
 
					var fixedFilterConfig = {
						entitySchema: this.entitySchema,
						filters: [
							{
								name: "PeriodFilter",
								caption: this.get("Resources.Strings.PeriodFilterCaption"),
								dataValueType: this.Terrasoft.DataValueType.DATE,
								startDate: {
									columnName: "StartDate",
									defValue: this.Terrasoft.startOfWeek(new Date())
								},
								dueDate: {
									columnName: "DueDate",
									defValue: this.Terrasoft.endOfWeek(new Date())
								}
							},
							{
								name: "Owner",
								caption: this.get("Resources.Strings.OwnerFilterCaption"),
								addOwnerCaption: this.get("Resources.Strings.AddEmployeeFilterCaption"),
								hint: this.get("Resources.Strings.SelectEmployeeFilterHint"),
								columnName: "Owner",
								defValue: this.Terrasoft.SysValue.CURRENT_USER_CONTACT,
								dataValueType: this.Terrasoft.DataValueType.LOOKUP,
								filter: myOwnerFilter,
								appendFilter: function(filterInfo) {
									var confirmedFilter;
									if (filterInfo.value && filterInfo.value.length > 0) {
										var inviteResponse = ConfigurationConstants.Activity.ParticipantInviteResponse;
										confirmedFilter = new Terrasoft.createFilterGroup();
										confirmedFilter.add("InviteResponseFilter", Terrasoft.createColumnFilterWithParameter(
												Terrasoft.ComparisonType.NOT_EQUAL,
												"[ActivityParticipant:Activity].InviteResponse",
												inviteResponse.Declined,
												Terrasoft.DataValueType.GUID));
										confirmedFilter.add("ActivityParticipantFilter", Terrasoft.createColumnInFilterWithParameters(
												"[ActivityParticipant:Activity].Participant",
												filterInfo.value));
									}
									return confirmedFilter;
								}
							}
						]
					};
					this.set("FixedFilterConfig", fixedFilterConfig);
				}
			},
			diff: /**SCHEMA_DIFF*/[
			]/**SCHEMA_DIFF*/
		};
	}
);

 

Илья, здравствуйте! Спасибо за решение, помогло.

Задам тут же ещё один вопрос: если мне нужен фильтр уже для выбранных активностей, то я могу изменения вносить уже в confirmedFilter? К примеру, в лукапе вывести не список контактов, а список типов, после чего задать: confirmedFilter.add("ActivityParticipantFilter", Terrasoft.createColumnInFilterWithParameters("Owner.Type", filterInfo.value); чтобы вывести задачи всех сотрудников

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

Добрый день!

Нужна помощь. Есть запрос на T-SQL вот такого вида: 

SELECT

    [tbl_BaseAssortment].[OfferingID] AS [OfferingID],

    [tbl_BaseAssortment].[Description] AS [Description],

    [tbl_BaseAssortment].[ChannelID] AS [ChannelID],

    [tbl_BaseAssortment].[StartDate] AS [StartDate],

    [tbl_BaseAssortment].[DueDate] AS [DueDate]

FROM

    [dbo].[tbl_BaseAssortment] AS [tbl_BaseAssortment]

WHERE([tbl_BaseAssortment].[StartDate] = 

    (SELECT

        MAX([tbl_BaseAssortmentLast].[StartDate]) AS [StartDate]

    FROM

        [dbo].[tbl_BaseAssortment] AS [tbl_BaseAssortmentLast]

    WHERE([tbl_BaseAssortment].[OfferingID] = [tbl_BaseAssortmentLast].[OfferingID] AND

        [tbl_BaseAssortment].[ChannelID] = [tbl_BaseAssortmentLast].[ChannelID] AND

        ([tbl_BaseAssortmentLast].[DueDate] >= getdate() OR

        [tbl_BaseAssortmentLast].[DueDate] IS NULL))))

Его нужно записать на EntitySchemaQuery в конфигурационной схеме. С фильтром совсем запутался...

Нравится

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

Добрый день. Если данный запрос необходимо выполнить из серверного кода - вам стоит посмотреть в сторону использования класса SELECT (более низкоуровневый класс чем ESQ). В случае клиентского кода необходимо добавлять View, поскольку конструкция SELECT FROM SELECT не поддерживается (если только не делать второй запрос в коллбеке первого).

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

Подскажите пожалуйста каким образом можно внедрить сторонние библиотеки JS в мобильную версию bpm online

Нравится

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

Здравствуйте, Андрей!

Подскажите, какую функциональность Вы хотите добавить сторонними библиотеками?

Pavel Bashtovoy, мне необходимо распрарсить xlsx файл, без отправки на сервер.

Андрей, добрый день!

Как вариант Вы можете создать отделньую схему и полностью скопировать код из этой библиотеки (т.е. метод "copy-paste"). А затем подключить как обычно в манифест CustomSchemas.

Пример подключения таких скриптов:

CustomSchemas: ['MobileActionCheckIn', 'MobileUtilities']

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

Здравствуйте. Очень полезная штука для меня оказалась - стартовый таймер в БП.

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

Запуск таймера происходит по времени UTC +3, хотя я создавал его в UTC +5.

БП, который запускался у меня по таймеру, должен создавать задачи, в которых явно присваивалось время старта, так вот время старта задачи получается вообще по времени UTC +2.

Ну и напоследок, управление этим волшебным инструментом - просто замечательное. Сохранив БП со стартовым таймером, мы получаем джоб в базе, и если у нас нет прямого доступа к ней, то сделать с ним ничего уже не получится, без помощи техподдержки. То есть не удалить, не изменить параметры запуска. Меняя параметры в объекте Стартовый таймер - мы просто получаем новый джоб.

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

Нравится

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

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

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

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

Добрый день, коллеги! Новый элемент работает с часовой зоной пользователя - а именно высчитывает offset и записывает в базе время в UTC. Также проверили работу джобов при изменении таймера - если это тот же элемент(т.е. изменить время запуска на текущем, а не удалить и добавить другой), джоб корректно изменяется согласно новых настроек. О том, что в данный момент отсутствуют пользовательские средства по удалению джобов(только SQL скрипты в конфигурации) разработчикам ядра известно, и они добавят соответствующий функционал в последующих релизах.

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

Коллеги, Доброго дня!

При создании контакта в поле тип выбирается значение из справочника: контактное лицо, клиент, сотрудник.

Каким образом можно скрыть значение из справочника со значением "сотрудник" в поле тип для всех пользователей кроме админа и hr-менеджеров?

Заранее спасибо.

 

Нравится

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

Добрый день.

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

1) Создать виртуальный атрибут булевого типа (для хранения информации о том, показывать значение пользователю или нет).

2) В методе onEntityInitialized проверять является пользователь админом или hr-менеджером при помощи esq и по результату запроса заполнять атрибут из пункта 1. Получить Id текущего пользователя можно кодом: Terrasoft.SysValue.CURRENT_USER.value.

3) В секцию атрибутов добавить фильтрацию к справочному полю где в методе фильтрации проверять значение виртуального атрибута и основываясь на нем добавлять фильтр который и будет отфильтровывать значение "сотрудник".

Пример использования фильтрации в атрибутах из конфигурации:

"Opportunity": {                                                               

dataValueType: Terrasoft.DataValueType.LOOKUP,

lookupListConfig: {

filter: function() {

return this.getOpportunityFilters();

}

}

}

Где имя фильтруемой колонки Opportunity, а метод filter возвращает набор фильтров, которые будут применены к esq при выборке значений для колонки Opportunity из бд.

 

 

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

Всем доброго времени суток. Версия 7.10.

При редактировании раздела Контрагенты выяснилось, что при добавлении новых типов страницы, их схемы наследуются от базовой BaseModulePageV2 (ESN) ( NUI ).

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

После сохранения вот такой правки, как на скриншоте, на странице Клиента остался первоначальный вариант страницы контакта (лежит в пользовательском пакете, наследуется от версии страницы в пакете UIv2 ), а страница Партнёра (лежит в Custom) почти пустая, занаследована от Базовой.

При попытке на странице редактирования схемы страницы Партнёра изменить родительский объект, вылезает сообщение об ошибке: "Невозможно установить родительский объект. Элемент c именем "SaveButtonCaption" уже существует в родительской схеме"

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

Нравится

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

Добрый день. Если я не ошибаюсь, то "элемент существует" - это всего лишь предупреждение. Попробуйте проигнорировать и сохранить страницу

Денис, здравствуйте!

Наследование типизированных страниц от базовой страницы раздела обеспечивает корректную работу с данными страницами в Мастере. При наличии типизированных страниц, унаследованных не от BaseModulePageV2, при внесении изменений Мастером в родительскую схему будут возникать конфликты, ошибки (когда страницы-наследники будут пытаться унаследовать какое-то новое поле, добавленное на страницу-родителя в Мастере).

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

- если все-таки удобно работать с Мастером, то, к сожалению, типизированные страницы необходимо настраивать с нуля. Аналитики продукта анализируют данную проблему и, возможно, в будущих релизах можно будет создавать типизированные страницы сразу на базе конкретной страницы раздела;

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

Рекомендации по формату схем для обеспечения совместимости с мастерами Вы найдете на SDK: https://academy.terrasoft.ru/documents/technic-sdk/7-10/trebovaniya-k-formatu-shem-dlya-obespecheniya-sovmestimosti-s-masterami

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

Всем доброго дня. Версия 7.10.

На вкладке Взаимосвязи страницы Контрагента есть деталь - Взаимосвязи.

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

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

Нравится

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

Здравствуйте, Денис!

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

Мы передали данное пожелание команде разработки для анализа возможности изменения функционала в будущих версиях.

Shevchenko Andrey,

Андрей, здравствуйте!

Так а в схемах нельзя поправить? Хотя бы в каких схемах происходит генерация диаграммы?

Здравствуйте, Денис!

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

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

Всем доброго времени суток. Версия 7.10.

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

Возможно ли в контролах использовать миксины, также, как и в обычных схемах? Может быть есть примеры, как правильно подключать миксин?

Сделал вот такой миксин:

 

Ext.define("Terrasoft.mixins.UsrMyMixin", {
    extend: "Terrasoft.Component",
    alternateClassName: "Terrasoft.UsrMyMixin",
 
    checkData: function(test){
console.log("ok");
    }
});

И подключил в контроле, занаследованном также от Component:

mixins: {
		UsrCheckScheduleDatesMixin: "Terrasoft.UsrCheckScheduleDatesMixin",
	},

При подключении, однако, в консоль вываливается ошибка:

file: undefined

 line: undefined

 column: undefined

 message: c is not a constructor 

Может где-то ещё что-то нужно добавить?

Нравится

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

Добрый день.

Контролы в bpm'online не поддерживают секцию mixins и код показанный на скриншоте работать не будет. Для уменьшения количества повторения кода, вы можете создать миксин или же просто модуль с методами и подключить его в define или же через- require. Затем нужные вам методы вызывать в нужном контексте используя методы call или же apply языка JavaScript. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Globa…

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

Терещук Сергей,

Сергей, я ориентировался вот на это: 

https://academy.terrasoft.ru/jscoresdk/source/diagram.html#Terrasoft-co…

Это контрол диаграммы. Там именно такая конструкция:

mixins: {
		connectorRemoval: "Terrasoft.ConnectorRemovalMixin"
	},

Ну и далее идёт вызов через this.mixins.connectorRemoval.init(this.getInstance());

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

То есть, мне следует создать свою версию components, внести туда свои дополнения, и занаследоваться от него.

В Components тоже есть похожая конструкция с mixins: https://academy.terrasoft.ru/jscoresdk/source/component.html#Terrasoft-…

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