Добрый день. Подскажите пожалуйста! Создал БП с условиями - простой и запланированной выдачи, где все действия происходят на преднастроенной странице, все отрабатывает нормально, но есть одно но при запланированной выдаче вернуться на преднастроенную страницу я могу только тогда когда сработает таймер(дата на которую планировал выдачу), а мне надо реализовать возможность попасть туда раньше времени для того чтобы что либо поменять или отменить.
Если вызывать новый БП и передавать туда данные то старый процесс так и будет висеть до определенной даты. Подскажите как мне быть в этой ситуации.

Сейчас попасть на мою страницу в БП могу только благодаря вопросу пользователю. А должен еще при нажатии на кнопку.

Нравится

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

Здравствуйте!

Задачу можно решить следующей настройкой процесса.

1. Создать служебную запись. В дальнейшем эта запись будет триггером для перехода на преднастроенную страницу. Условно – создать активность.
2. Элемент [Исключающее ИЛИ по событиям].
Одно ветка ведет к таймеру.
Вторая ветка ведет к элементу [Обработка сигнала]. Ожидает изменения в объекте, где Id = Пункт 1. Id
3. Исключающее ИЛИ. Принимает на вход обе ветки.
5. Преднастроенная страница.

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

"Зарицкий Олег" написал:

Спасибо, Олег

"Зарицкий Олег" написал:

1. Создать служебную запись. В дальнейшем эта запись будет триггером для перехода на преднастроенную страницу. Условно – создать активность.


Здравствуйте, а можно подробнее про этот пункт? Не очень понял.

Здравствуйте!

1. Создать служебную запись. Подразумевается – создать запись в любом объекте. Например, элемент [Добавить данные] в объект Активность. В дальнейшем изменения в этой записи приведут к тому, что процесс сразу перейдет к выполнению преднастроенной страницы (не дожидаясь таймера).

2. В случае с приведенным примером (когда служебная запись представлена в виде активности) – в элементе [Обработка сигнала] необходимо ожидать изменения записи в объекте Активности, где Id = Пункт 1.Id

В результате – преднастроенная страница откроется если прошло время, указанное в таймере, ИЛИ будет изменена активность.

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

Коллеги, всем привет!

У нас возникла проблема. При настройке системы все изменения сохраняются в созданный нами пакет "Roscap_Main". В какой-то момент название этого пакета в списке стало выделено черным цветом и не получается заблокировать ряд элементов для фиксации изменений в хранилище. Всплывает ошибка "Для заданного локального пути не указан путь к хранилищу". Подскажите, пожалуйста, что значит выделение названия пакета черным цветом и почему оно не снимается? И как можно исправить ошибку блокирования элементов для фиксации их в хранилище.

Скриншот - https://db.tt/a3SKjesC2q
версия - 7.9

Нравится

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

Приветствую!

Попробуйте установить в Terrasoft.WebApp\Web.config

  <add key="UseSvn" value="false" />

Тогда не будет возможности использовать SVN. Он как раз нужен.

Очистите кэш SVN (содержимое %TEMP%\%APPLICATION%\%WORKSPACE%\...) и авторизируйтесь в хранилище.

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

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

Немогу словить в каком модуле реализовано создание контакта, да и в модуле ли вообще оно реализовано? ВОзможно кто-то решал подобное?
Есть конечно один вариант, при котором будет открываться страница контакта - это в обьекте Контакт сделать какое-то поле обьязательным на уровне приложения. Но это не выход...

Нравится

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

Здравствуйте!

Функциональность создания новой записи из справочника реализована в LookupQuickAddMixin.

В последней релизной версии уже встроена функциональность открытия карточки перед созданием объекта, в методах tryCreateEntityOrOpenCard->openPageForNewEntity.

За эту функциональность отвечает фича UseSilentCreation.

"Demchenko Olha" написал:

Здравствуйте!

Функциональность создания новой записи из справочника реализована в LookupQuickAddMixin.

В последней релизной версии уже встроена функциональность открытия карточки перед созданием объекта, в методах tryCreateEntityOrOpenCard->openPageForNewEntity.

За эту функциональность отвечает фича UseSilentCreation.

Ольга, спасибо!

Я, как раз перед Вашим ответом нашел нужный модуль LookupQuickAddMixin :smile:
Заместил его, и добавил необходимое условие, чтобы срабатывал метод openPageForNewEntity.
Все работает корректно!

Я попробовал в 7.16 менять эту фичу, но она ни на что не повлияла. Как была возможность создать новую запись прямо из поля, так и осталась

В 7.16 карточка лида выглядит уже не так, как в первом сообщении темы. Возможно, и логика менялась. Где именно вводите и создаётся запись?

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

В таблице SysAdminUnitType (Типы административных юнитов, на данный момент мне все понятно со всеми типами кроме одного - "Team" (3)

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

Нравится

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

Здравствуйте,
на карточке “группы” есть поле “гид” и деталь “контакты группы”. Необходимо при изменении поля “гид” пройтись по всем контактам в детали и используя значение поля “сделка” из каждого контакта, изменить поле “гид” для всех соответсвующих сделок этих контактов в разделе “сделки”.
Реализовали данную задача с помощью БП, но меняется только одна запись, подскажите пожалуйста, как можно читать всю выборку записей из детали и для множества соответствующих записей в другом разделе менять поле.

Нравится

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

Здравствуйте!

Судя по описанию необходимо работать одновременно с коллекцией данных, а не первой выбранной записью.
Пока с коллекцией может работать только элемент "Добавить данные" в режиме выборки.
Для решения вашей задачи можно использовать [Задание-сценарий], написать в нем интересующий запрос.
Или создать циклический процесс, который будет обрабатывать 1 контакт за 1 итерацию в цикле.

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

int count = Get<int>("count");
int count2 = count - 1;
Set<int>("count", count2);
return true;

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

Здравствуйте!

Алгоритм следующий:
А. Добавить в объект Контакты служебное поле с типом Логическое, например ForCycle.
Б. Первый процесс запускается по нужному событию и устанавливает для всех контактов ForCycle = true.
В. Второй процесс циклический:
1) читать кол-во контактов, у которых ForCycle = true
2) поток по умолчанию ведет к завершению процесса
3) условный поток: [Читать кол-во записей] > 0 - ведет к элементу Читать первый контакт, где ForCycle = true. На этом этапе мы получим Id первого интересующего контакта - > обрабатываем контакт - > устанавливаем ForCycle = false -> в конце поток перехода ведет к Пункт 1

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

Спасибо, получилось.

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

Если Вам необходимо управлять доступностью (enabled) или видимостью (visible) вы биндите их на атрибут (который предварительно создаете) и в последующем меняя значение атрибута - управляете соответствующим значением.
И все таки... (ради спортивного интереса, и для более углубленно понимания системы и применяемых в ней механизмов)
Каким образом в коде можно подступиться до элемента/поля и воздействовать на его свойства ?
(Это же компоненты Ext.JS насколько я понимаю)
Ну естественно я говорю не о том чтобы получить DOM-объект по имени компонента или по CSS-селектору (Ext.get() / Ext.getCmp()) и применить к нему стили инлайново.
Я про то как доступиться до конфига, изменить и инициализировать изменения ?

PS: Есть где ни будь кстати материал по разработке и внедрению кастомных элементов ? (быстрое гугление по форуму не помогло, хотя возможно я некорректно формулировал поисковый запрос :))

Нравится

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

Здравствуйте, Илья.

Помимо ExtJs в bpm'online также используется библиотека BackboneJs. Если на момент построение модели в ViewModel генераторе не были определены биндинги - изменить значение какого-либо свойства в рантайме Вы уже не сможете. Разве что писать свой пользовательский генератор.

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

Вопрос:
Как создать свой контрол?
Ответ:

контрол:

Ext.ns("Terrasoft");
/**
 * @class Terrasoft.controls.UsrMyControl
 * Класс элемента управления для отображения
 */
Ext.define("Terrasoft.controls.UsrMyControl", {
	extend: "Terrasoft.Component",
	alternateClassName: "Terrasoft.UsrMyControl",
	mixins: {
	},
	myParam: "",
	/**
	 * @inheritdoc Terrasoft.Component#tpl
	 * @protected
	 * @overridden
	 */
	tpl: [
		/*jshint white:false */
		"<div id='{id}-usr-my-control' class='{wrapClass}'>",
		"{myParam} test-test-test",
		"</div>"
		/*jshint white:true */
	],
	getTplData: function() {
		var tplData = this.callParent(arguments);
		tplData.myParam = this.myParam;
		this.updateSelectors(tplData);
		return tplData;
	},
	/**
	 * @inheritDoc Terrasoft.Component#init
	 * @protected
	 * @overridden
	 */
	init: function() {
		this.callParent(arguments);
		this.addEvents(
			"myMethod"
		);
	},
	/**
	 * @inheritDoc Terrasoft.Component#constructor
	 * @overridden
	 */
	constructor: function() {
		this.callParent(arguments);
	},
 
	updateSelectors: function(tplData) {
		var id = tplData.id;
		var baseIdSuffix = "-usr-my-control";
		var selectors = this.selectors = {};
		selectors.wrapEl = "#" + id + baseIdSuffix;
		return selectors;
	},
	/**
	 * Подписка на события элементов элемента управления
	 */
	initDomEvents: function() {
		this.callParent(arguments);
		var wrapEl = this.getWrapEl();
		if (wrapEl) {
			wrapEl.on("click", this.onClick, this);
		}
	},
	/**
	 * Обработчик события click на основном элементе
	 * @param event
	 */
	onClick: function(event) {
		event.stopEvent();
		this.fireEvent("myMethod", this);
	},
	/**
	 * Возвращает конфигурацию привязки к модели. Реализует интерфейс миксина {@link Terrasoft.Bindable}.
	 * @overridden
	 */
	getBindConfig: function() {
		var parentBindConfig = this.callParent(arguments);
		var bindConfig = {
			myParam: {
				changeMethod: "setMyParam"
			}
		};
		Ext.apply(bindConfig, parentBindConfig);
		return bindConfig;
	},
 
	setMyParam: function(val) {
		this.myParam = val || this.myParam;
		if (this.allowRerender()) {
			this.reRender();
		}
	},
	/**
	 * @overridden
	 * @inheritdoc Terrasoft.Component#destroy
	 */
	onDestroy: function() {
		var wrapEl = this.getWrapEl();
		if (wrapEl) {
			wrapEl.un("myMethod", this.onClick, this);
		}
		this.callParent(arguments);
	},
	/**
	 * Устанавливает значение флага только для чтения
	 * @param {Boolean} readonly Значение флага только для чтения. Если true - элемент управления устанавливается в
	 * режим только для чтения, false - рабочий режим элемента управления
	 */
	setReadonly: function(readonly) {
		if (this.readonly === readonly) {
			return;
		}
		this.readonly = readonly;
		if (this.allowRerender()) {
			this.reRender();
		}
	}
});

генератор:

 define("UsrMyControlGenerator", ["UsrMyControlGeneratorV2Resources", "terrasoft", "ext-base", "UsrMyControl"],
		function(resources) {
	var UsrMyControlGenerator = Ext.define("Terrasoft.configuration.UsrMyControlGenerator", {
		extend: "Terrasoft.ViewGenerator",
		alternateClassName: "Terrasoft.UsrMyControlGenerator",
		generateUsrMyControl: function(config) {
			var usrMyControl = {
				className: "Terrasoft.UsrMyControl",
				id: config.name + "UsrMyControl",
				selectors: {wrapEl: "#" + config.name + "UsrMyControl"},
				myParam: {bindTo: config.getMyParam},
				myMethod: {bindTo: config.myMethod}
			};
			if (!Ext.isEmpty(config.wrapClassName)) {
				usrMyControl.classes = {
					wrapClassName: config.wrapClassName
				};
			}
			return usrMyControl;
		}
	});
	return Ext.create(UsrMyControlGenerator);
});

схема:

 define("CasePage", ["CasePageResources", "terrasoft", "UsrMyControlGeneratorV2", "UsrMyControl"],
	function(resources, Terrasoft) {
	return {
		entitySchemaName: "Case",
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		attributes: {
			"Test": {
				"dataValueType": Terrasoft.DataValueType.TEXT,
				"type": Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
				"value": "123"
			}
		},
		diff: /**SCHEMA_DIFF*/[
			{
				"operation": "insert",
				"parentName": "SolutionTab_gridLayout",
				"name": "UsrTest",
				"propertyName": "items",
				"values": {
					"className": "Terrasoft.UsrMyControl",
					"layout": { "colSpan": 24, "rowSpan": 1, "column": 0, "row": 4 },
					"generator": "UsrMyControlGenerator.generateUsrMyControl",
					"visible": true,
					"getMyParam": "getMyParam",
					"myMethod": "myMethod"
				}
			}
		]/**SCHEMA_DIFF*/,
		methods: {
			onEntityInitialized: function() {
				this.callParent(arguments);
				// just for debug:
				document.scope = this;
			},
			getMyParam: function() {
				return this.get("Test");
			},
			myMethod: function() {
				var oldTest = this.get("Test");
				this.set("Test", oldTest + "!");
			}
		},
		rules: {}
	};
});
Показать все комментарии

Версия приложения 7.9.2.2410

В дизайнере системы - Настройка рабочих мест, обнаружен занятный баг интерфейса:
Если у рабочего места большой список разделов (более 10 шт.) то пункты свыше 10-го скрываются под cut "Показать больше", по клику на который открывается список целиком, там у элементов присутствуют пункты "стрелки", нажимая на которые можно определить позицию раздела.
Так вот если вы открыли кат и единожды подняли или опустили пункт в открывшемся списке, кат снова закрывается, таким образом если вам необходимо поднять пункт с последнего места (а на него по умолчанию становятся все вновь добавленные разделы), если у вас например 16 разделов, то Вам придется 6-ть раз открывать кат, по идее кат не должен скрываться если идет взаимодействие с кнопками регулирующими положение, да и сами кнопки в идеале должны поддерживать "залипание" (чтобы не 16-ть раз кликнуть а зажать и ждать пока пункт поднимется на нужную позицию)

Нравится

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

Здравствуйте, Илья!

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

Мотков Илья,

Подскажите, пожалуйста, решилась ли каким-то образом данная проблема?

Небеддаг Иван Владимирович пишет:

решилась ли каким-то образом данная проблема?

заместите SysModuleInWorkplaceDetailV2 

define("SysModuleInWorkplaceDetailV2", ["terrasoft", "LocalizableHelper", "ServiceHelper",
	"SysModuleInWorkplaceDetailV2Resources"],
	function(Terrasoft, LocalizableHelper, ServiceHelper, resources) {
		return {
			entitySchemaName: "SysModuleInWorkplace",
			methods: {
				setPosition: function(recordId, position, callback, scope) {
					var data = {
						tableName: "SysModuleInWorkplace",
						primaryColumnValue: recordId,
						position: position,
						grouppingColumnNames: "SysWorkplaceId"
					};
					var count = this.getGridData().getCount();
					var profile = this.get("Profile");
					this.set("RowCount", profile &amp;&amp; profile.DataGrid.isTiled ? count : count / 2);
					ServiceHelper.callService("RightsService", "SetCustomRecordPosition", callback, data, scope);
				}
			}
		};
	});

 

Здравствуйте, Илья. Данное поведение исправлено в версии 7.12.0.

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

Если складываете View для активностей с группировкой, например, по началу и концу и при этом есть процессные активности, у которых начало расчитывается как временной интервал между now и некоей датой, можете получить проблемы с секундами и милисекундами. Поэтому при группировке активностей по дате лучше всего применять вот такой каст в sql:

CAST(CONVERT(varchar(16), [StartDate], 20) AS datetime)

где StartDate - поле с датой до милисекунд.

Нравится

Поделиться

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

Добрый день!
Возник такой вопрос - после нажатия на кнопку Печать в Счете система просит открыть или сохранить печатную форму Счет на оплату, имея определенное название (смотреть вложенный файл). Как можно изменить название печатной формы при сохранении документа?

Нравится

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

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

Если в настройках браузера активна функция "Спрашивать куда сохранять файл перед скачиванием", то при скачивании ПФ у Вас будет появлятся окно, где Вы указываете путь сохранения файла и можете изменить его название (см. скриншоты). Также, Вы можете изменить название ПФ в справочнике "Печатные формы".

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

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

onEntityInitialized: function() {
                                if (this.isAddMode() || this.isCopyMode()) {
//код
}
}

Но как узнать данные источника откуда копируется раздел ?

Нравится

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

Если это isCopyMode то id от кого скопировались узнать можно так:
this.get("SourceEntityPrimaryColumnValue")
Если isAddMode, то понятно, что нет никакого источника.

Максим спасибо.
Буду делать копирование так

onEntityInitialized: function() {
				if (this.isCopyMode()) {
 
this.get("SourceEntityPrimaryColumnValue"); //id источника
//код копирования
 
				}

вопрос...как я понимаю пока еще нет же созданной записи в БД?

"Юсупов Марат" написал:как я понимаю пока еще нет же созданной записи в БД?

Все верно, данной записи еще нет в бд, но вы можете вызвать:
this.save({silent:true}) что сохранит данную запись в бд, не закрывая карточку. После чего можно будет добавлять в неё и записи деталей.

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