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

Нравится

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

Bind Visible по условию чем плох?

Добрый вечер.

Создаете Ext класс, например, "Terrasoft. TextEdit"

Ext.create("Terrasoft. TextEdit", {...})

 – примеры можно поискать в коробке. Потом находите компонент, в который хотите добавить новый элемент

var cmp = Ext.getCmp()

В полученном компоненте в свойство items добавляете его

cmp.items.add(«новий компонент»)

 Вызываете ререндер, что бы новый компонент отобразился 

cmp.reRender()

 

VladKapitanchyk,

Добрый день. Мне надо после загрузки вкладки добавить.

Пример.

{
		"operation": "insert",
		"name": "Tab4040b433TabLabelGridLayoutef7de6d2",
		"values": {
			"itemType": 0,
			"items": [],
			"afterrender": {
				"bindTo": "loadWidgetModule"
			},
			"afterrerender": {
				"bindTo": "loadWidgetModule"
			}
		},
		"parentName": "Tab4040b433TabLabelGroup9e196572",
		"propertyName": "items",
		"index": 0
	},
loadWidgetModule: function (config) {
				debugger;
 
				var cmp =Ext.getCmp("UsrUsrVwSysAccountLog1PageTab4040b433TabLabelGridLayoutef7de6d2GridLayout");// Ext.getCmp("Tab4040b433TabLabelGridLayoutef7de6d2");
				// this.addFields();
				var labelConfig = Ext.create("Terrasoft.Container", {
					id: "headerContainer",
					items: [
						{
							className: "Terrasoft.Label",
							id: "headerLabel",
							selectors: {
								wrapEl: "#headerLabel"
							},
							caption: "Изменение полей",
 
						}
					]
				});
				 cmp.items.add(labelConfig);
				 cmp.reRender();
			},

но при добавлении элемента (items.add) ошибка  message: Uncaught Terrasoft.ArgumentNullOrEmptyException: Несуществующий или пустой аргумент  в render

Евгений Волоцкой,

В контейнер нужно тоже передавать объект Ext -Ext.create("Terrasoft.Label"…)

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

Добрый день.

Есть задача добавлять в продукт сопряженные продукты (нечто вроде матрицы). При этом есть требование, чтобы при добавлении сопряженных продуктов были доступны все способы фильтрации и поиска - как в разделе Продукты (в том числе, Группы и Каталог). В связи с этим было принято решение создать страницу CrossProductSectionV2, унаследованную от ProductSectionV2. Эта страница открывается при нажатии нужной копки на странице ProductPageV2. Пробовали два подхода к открытию, но оба сопряжены с определенными проблемами. 

1. Через this.sandbox.loadModule

			addProductsExtended: function() {
				/// <summary>Открывает раздел продуктов для выбора и добавления в матрицу.</summary>
				var parameters = {
					viewModelConfig: {
						NrbBaseProduct: this.getBaseProduct()
					}
				};
 
				var instanceConfig = {
					schemaName: "CrossProductSectionV2",
				    isSchemaConfigInitialized: true,
				    entitySchemaName: "Product",
				    useHistoryState: true,
				    isSeparateMode: true,
				    isInChain: true
				};
				var config = {
					renderTo: "centerPanel",
				    id: this.getCrossProductSectionModuleId(),
				    instanceConfig: instanceConfig,
				    parameters: parameters,
				    keepAlive: true
				};
 
				this.sandbox.loadModule("SectionModuleV2", config); 
 
			},
 
			getCrossProductSectionModuleId: function() {
				/// <summary>Формирует идентификатор модуля для добавления продуктов в матрицу.</summary>
				return this.sandbox.id + "_CrossProductSectionV2";
			},
 
			getBaseProduct: function() {
				/// <summary>Вовзращает идентиификатор базового продукта для матрицы.</summary>
				var value = this.get("Id") || this.get("PrimaryColumnValue");
				var displayValue = this.get(this.primaryDisplayColumnName);
				var baseProduct = {
					value: value,
					displayValue: displayValue
				};
				return baseProduct;
			}

В это случае инициализация базового продукта NrbBaseProduct (к которому привязываем сопряженные) в CrossProductSection происходит без проблем. Но есть ряд проблем с отображением и последующей выгрузкой модуля CrossProductSection.

Немного некорректно отображается содержимое GridUtilsContainer (съедена верхняя часть), также показан какой-то toggle при нажатии на который - чистый лист (хеш при этом сменяется на что-то невразумительное - без имени страницы ProductPageV2)

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

 

 

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

 

Ровно то же самое происходит и при нажатии кнопки Закрыть - разве что toggle также исчезает

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

На кнопку Закрыть в CrossProductSectionV2 повешен простой обработчик

			onCloseButtonCustomClick: function() {
				/// <summary>Обработчки нажатия на кнопку Закрыть.</summary>
 
				this.sandbox.publish("BackHistoryState");
			},

 

2. Другой способ открытия - через PushHistoryState

			addProductsExtended: function() {
				/// <summary>Открывает раздел продуктов для выбора и добавления в матрицу.</summary>
				var parameters = {
					viewModelConfig: {
						NrbBaseProduct: this.getBaseProduct()
					}
				};
				var stateObj;
				var requestUrl;
		  		var params = this.sandbox.publish("GetHistoryState");
				stateObj = {
					schemaName: "CrossProductSectionV2",
				    isSchemaConfigInitialized: true,
				    entitySchemaName: "Product",
				    useHistoryState: true,
				    isSeparateMode: true,
				    isInChain: true,
				    parameters: parameters,
				    id: this.getCrossProductSectionModuleId()
				};
				requestUrl = "SectionModuleV2/CrossProductSectionV2";
 
				this.sandbox.publish("PushHistoryState", {
					hash: requestUrl,
					stateObj: stateObj
				});
			},

В этом случае открытие и отображение, происходит нормально, но есть проблема с инициализацией базового продукта. Похоже, что объект parameters не обрабатывается. Пока использую решение с инициализацией через публикацией сообщения, но этот подход имеется свой недостаток. В частности после обновления страницы по F5 продукт уже не сможет проинициализироваться.

Также Закрытие, в случае если, открывались и закрывались Группы и/или Расширенная фильтрация произойдет только после n-го нажатия на кнопку Закрыть, где n - число раз когда открывали Группы или Расширенную фильтрацию.

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

Нравится

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

Что в это время отображается в консоли и на панели Network? Все запросы корректны? Ошибок никаких нет?

Да, все запросы корректны, ошибок в консоли не наблюдается. Есть только предупреждения при открытии CrossProductSection, что на скрине

Можно ещё третий подход: сделать в разделе продуктов действие «Сопрячь» с выбором нескольких записей. Выбираете два продукта, пользуясь группами, каталогом и прочим, затем запускаете действие, а оно создаёт запись в объекте детали связи многих ко многим одного продукта с другим.

Александр, спасибо за ответ. Эту задачу на текущий момент решили способом 2, устранив вот этот момент

Также Закрытие, в случае если, открывались и закрывались Группы и/или Расширенная фильтрация произойдет только после n-го нажатия на кнопку Закрыть, где n - число раз когда открывали Группы или Расширенную фильтрацию.

Устранили путем переопределения пары методов на пустые

			removeCardHistoryState: Terrasoft.emptyFn,
 
			setInitialHistoryState: Terrasoft.emptyFn,

Но дальше  - больше. Теперь хотят, чтобы во всех местах, где есть lookup поля Продукт - была возможность поиска по группам и Каталогу. А если пойти еще далее, то, пожалуй, во всех справочниках, по которым в системе зарегистрирован раздел, чтобы была возможность отображать группы с возможностью управления через lookupListConfig - по аналогии с действиями, которые можно скрыть, указав hideActions: true. Но это уже, пожалуй, идея для будущих улучшений продукта.

Орленко Андрей Николаевич пишет:

Теперь хотят, чтобы во всех местах, где есть lookup поля Продукт - была возможность поиска по группам и Каталогу. А если пойти еще далее, то, пожалуй, во всех справочниках, по которым в системе зарегистрирован раздел, чтобы была возможность отображать группы с возможностью управления через lookupListConfig - по аналогии с действиями, которые можно скрыть, указав hideActions: true. Но это уже, пожалуй, идея для будущих улучшений продукта.

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

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

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

Нравится

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

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

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

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

Либо вариант, сделать действие "Чек-ин" обязательное (делается через справочник "Правила полевых продаж" - http://prntscr.com/jjhv8n.

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

Коллеги всем доброго времени суток!

Столкнулся с такой проблемой:

Формируем запрос к БД через ESQ - http://prntscr.com/jj0e03

далее делаем выборку из сформированной коллекции - http://prntscr.com/jj0efz

Однако при выборке вылетает ошибка - http://prntscr.com/jj0et9

Смотрим как сформировался SQL  - http://prntscr.com/jj0fa1

При этом var esqSmsStatus = esq.AddColumn("SmsStatus").Name; равно http://prntscr.com/jj0ka4

Кто с таким сталкивался? Прошу помочь.

Заранее благодарю.

Нравится

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

Недавно вроде отвечал на подобный вопрос. Попробуйте esq.AddColumn("SmsStatus.Id").Name. 

Чисто опытным путём было выяснено, что простые колонки и колонки, до которых можно просто добраться (пример: колонка Status, справочная. добавляем в запрос - esq.AddColumn("Status"). берём в результатах - p.GetTypedColumnValue<Guid>("StatusId") или p.GetTypedColumnValue<string>("StatusName")). Грубо говоря имеет смысл обозначать через Name только сложные пути, а-ля "Lead.QualifiedContact.Department.Name"

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

Благодарю!

В серверном коде при работе с этой функцией перед Id нет точки:

Page.DataSource.ActiveRow.GetTypedColumnValue&lt;Guid&gt;("AccountId"));

Отображаемое значение справочного поля тоже получается без точки:

entity.GetTypedColumnValue&lt;string&gt;("FacilityName");

 

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

В наших процессах нужно ставить задачи на группы людей. Делаю так - создаю Активность, добавляю участников в категории Ответственный, скриптом обнуляю ответственного у самой Активности. 

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

Проблема возникает с миникарточкой. Когда работник пытаюсь завершить Активность из мини-карточки, у нее ответственный подставляется ответственным из объекта, к которому Активность привязана, например, Контакт.

Есть несложный способ побороть это? Или надо городить свою мини-карточку, обработку Ответственного и т.д.?

Нравится

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

Добрый день.

При нажатии на «Завершить задачу» в мини карточке активности «ActivityMiniPage» вызывается метод «onChangeStatusButtonClick». Можете его заместить и добавить свою логику.

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

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

Базовая цена, плюс скидки:

За объём +3%

За удалённость +1%

За самовывоз +10% и т.д.

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

Нравится

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

Вы хотите эти скидки делать на уровне продукта в счёте или на уровне счёта?

Хороший вопрос... Нет, наверное на уровне в счёте лучше!

Добрый день, Алексей!

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

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

Пробую реализовать пример из обсуждения:

https://community.terrasoft.ru/questions/ctenie-dannyh-rezultiruusaa-ko…

Получаю ошибку на этапе скрипт-таска

System.NullReferenceException: Object reference not set to an instance of an object.
   at Terrasoft.Core.Process.UsrCollectionOfSmthMethodsWrapper.ScriptTask1Execute(ProcessExecutingContext context)
   at Terrasoft.Core.Process.ProcessFlowElement.Execute(ProcessExecutingContext context)

 В процессе чтение данных, скрипт-таск, автогенерируемая страница. Читаем контакты, созданные за месяц, пытаемся их записать в параметр, чтобы показать на странице.

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

Нравится

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

Добрый день.

Скорее всего вы неправильно читаете данные.

Код который работает:

EntityCollection entities = Get&lt;EntityCollection&gt;("ReadDataUserTask1.ResultEntityCollection");
Set("Param1", entities);

Параметр "Param1" имеет тип - "Коллекция объектов (EntityCollection)".

ReadDataUserTask1 - имя элемента (выберите элемент – расширенный режим (три точки вверху справа) - имя)

Проверьте настройку «Для интерпретируемого процесса», в элементе ScriptTask зайти в «Расширенный режим» (три точки вверху) – должна быть включена.

VladKapitanchyk,

А как в вашем случае использовать результирующую коллекцию?

Пытаюсь получить список записей по условию, чтобы записать их в Notes или в тело письма.

ZAN,

EntityCollection это класс, который наследуется от LinkedList<Entity> (базовый C# класс), поэтому содержит базовые методы для работы с коллекцией. https://msdn.microsoft.com/en-us/library/kb834fyk(v=vs.110).aspx

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

Добрый день!

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

Идея такая: в платежных реквизитах Контрагента (нашей компании) сохраняем скан подписей с печатями для счета, при печати счета на оплату подставляем этот скан.

Нравится

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

Борис, здравствуйте!

 

Вывод изображений происходит по аналогии с другими полями. Вы выводите поле с типом «Изображение».

Данный вопрос уже ранее обсуждался - https://community.terrasoft.ru/questions/pecatnye-formy.

Добрый день!

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

Уменя все получилось после ознакомления инфы по ссылке в комментарии Дмитрия.

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

Коллеги, доброго времени суток!

Подскажите пожалуйста:

В разделе "Счета" при изменении количества/цен продуктов идет автоматический пересчет "Суммы" счета. Как я понял код, отвечающий за изменение находится в пакете Invoice => схеме объекта InvoiceProduct => подпроцессе SubProcessScriptAmountChange => внутри скрипта ScriptAmountChange, который отрабатывает при получении сообщения события InvoiceProductSaved или InvoiceProductDeleted. Поиск по сообществу показал, что видимо просто так переопределить код внутри скрипта нельзя, если он не вынесен в метод. Чтобы заменить логику его работы нужно создать свой подпроцесс с входами через те же сообщения (но со своими названиями) и в конце вызываемого скрипта перед return вписать

ActivatedEventElements.Remove("InvoiceProductSaved");

ActivatedEventElements.Remove("InvoiceProductDeleted");

что я и сделал, создал подпроцесс по образу и подобию с родительским (два входных сообщения через исключащее "ИЛИ" по безусловной связи идут в скрипт), однако после сохранения, публикации и обновлении стурктуры БД дополнительная логика не отрабатывает, из чего я делаю вывод, что до скрипта почему-то дело не доходит.

У моих входных событий совпадают с родительскими поля "Сообщение" (InvoiceProductSaved и InvoiceProductDeleted), но отличаются "Название" (иначе компилятор предупреждает, что override неправильно делаю, и получается только hide.. ну и всё равно не работает), поле "Условие" в связи от исключащего ИЛИ пустое, судя по "Исходному коду" это как раз то, что нужно, т.к. в этом случае функция всегда возвращает true.

Пытался и напрямую оба события на скрипт завязать - всё равно не работает.

Вопрос соответственно - что я делаю не так?

Нравится

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

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

Описанное решение выглядит правильно. 

Для перекрытия логики по родительскому сигналу, необходимо в дочернем БП объекта подписаться на аналогичное событие объекта и в скрипте перед return true  вставить:

if (ActivatedEventElements.Contains("InvoiceProductSaved")) {

&nbsp;&nbsp;&nbsp;&nbsp;ActivatedEventElements.Remove("InvoiceProductSaved")

}

Проверьте, что БП в дочернем объекте помещен в "Событийный подпроцесс".

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

Спасибо!

Попробовал в другом объекте (OrderProduct) проверить. Создал в процессе замещающего объекта событийный подпроцесс, в него поместил одно начальное событие (сообщение OrderProductSaved) из него прямой переход на скрипт, в котором три строчки:

global::Common.Logging.ILog _Logger = global::Common.Logging.LogManager.GetLogger("Client");

_Logger.Info("Order product saved event test");

return true;

Одновременно в переопределенный метод RecalculateOrderAmount вписываю в начале:

global::Common.Logging.ILog _Logger = global::Common.Logging.LogManager.GetLogger("Client");

_Logger.Info("Order product saved event test 2, "+GetPropertiesData());

Метод вызывается только в родительском процессе по цепочке от сообщений OrderProductSaved или OrderProductDeleted.

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

Что может быть не так или может быть есть какая-то статья или инструкция для чайников как правильно создавать дополнительные обработчики стандартных событий в процессах замещающих объектов?

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

Добрый день!

Проверила ваш кейс у себя, всё получилось.

Вот как я делала:

Событийный подпроцесс - http://prntscr.com/jhpu81

Задание-сценарий - http://prntscr.com/jhpuoz

Добавила продукты в счете - http://prntscr.com/jhpuz6

Сумма не считается - http://prntscr.com/jhpv9a

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

Не могу установить параметр БП типа EntityCollection с именем ActualPOAs. Делаю в коде:

var esq = new EntitySchemaQuery(context.UserConnection.EntitySchemaManager, "UsrPowerOfAttorney");
esq.AddAllSchemaColumns();
EntityCollection ActualPOAs = esq.GetEntityCollection(context.UserConnection);
// Упадет в следующей строке
Set<EntityCollection>("ActualPOAs", ActualPOAs);

После чего получаю исключение (ниже). Что я делаю не так?

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: The best overloaded method match for 'Terrasoft.Core.Process.IProcessParameterStore.SetParameterValue(System.Guid, string, string)' has some invalid arguments at CallSite.Target(Closure , CallSite , IProcessParameterStore , Guid , String , Object ) at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid4[T0,T1,T2,T3](CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3) at Terrasoft.Core.Process.ProcessParameterInfoComposer.UpdateParameterInfoValue[T](Guid processUId, ProcessParameterInfo parameterInfo, String parameterPath, T value) at Terrasoft.Core.Process.ProcessModel.SetParameterValue[T](FoundParameterData result, T value) at Terrasoft.Core.Process.ProcessModel.TrySetValue[T](ProcessSchema processSchema, String propertyPath, T value) at Terrasoft.Core.Process.ProcessModel.Set[T](String propertyPath, T value) at Terrasoft.Core.Process.PowerOfAttorneyPackCheckMethodsWrapper.ScriptCheckPOAExecute(ProcessExecutingContext context) at Terrasoft.Core.Process.ProcessFlowElement.Execute(ProcessExecutingContext context)

Нравится

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

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

Необходимо параметру ActualPOAs просто присвоить полученную коллекцию:

ActualPOAs = esq.GetEntityCollection(context.UserConnection);

На элементе задание-сценарий перейти в расширенный решим и снять галочку "Для интерпретируемого процесса".

В настройках процесса установить галочку "Компилировать".

Demchenko Olha,

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

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

В функционале БП во-первых, не предусмотрено присваивание коллекций методом Set в интерпретируемых процессах, во-вторых, таймеру все равно компилируемый процесс или интерпретируемый.

Золотарев Артем Андреевич,

https://community.terrasoft.ru/questions/startovyi-taimera-v-bp - отсюда, ответ Логвин Андрей Витальевич: "Запуск компилируемых процессов по стартовому таймеру реализован в версии 7.11.3 и выше."

Правильно я понимаю,что 

ActualPOAs = esq.GetEntityCollection(context.UserConnection); будет работать в интерпретируемом процессе?

 

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

Попробуйте сделать, как написала Demchenko Olha и протестируйте работу БП.

Если не сработает ожидаемым способом и у вас версия до 7.11.3 отключите для БП признак "Компилируемый", а для задания-сценария уберите галочку "Для интерпретируемого процесса", это должно работать нормально.

А вот для 7.11.3 точно нормально работает и для компилируемого БП.

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

ActualPOAs = esq.GetEntityCollection(context.UserConnection); - работает только для компилируемого задания-сценария

Золотарев Артем Андреевич,

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

https://academy.terrasoft.ru/documents/technic-bpms/7-12/element-proces…, добавьте, что не методы Get и Set не работают для коллекций объектов. Иначе до этого догадаться, мягко говоря, непросто и отсюда начинаются бодания с ТП, которая просит денег (более дорогой пакет поддержки) за объяснение где ваша документация не соответствует реальности. А это уже просто не лезет ни в какие ворота!

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