как программно посчитать общую стоимость из детали продукты по колонке стоимость.

В самой детали программно рассчитала стоимость.

Нравится

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

Добрый день, Алёна!

Детализируйте, пожалуйста, свой запрос, так как из описания не совсем понятна суть. Вы уже сделали пересчет в детали и теперь хотите данное значение видеть в отдельном поле карточки? В таком случае вопрос решаем через бизнес-процесс элементами чтение данных и добавление данных. Если же речь о том, что нужно рассчитать стоимость на основании поля в детали (+ еще др. полей), то в таком случае можно использовать элемент "Формула" или воспользоваться инструкцией по добавлению вычисляемых полей полями https://academy.terrasoft.ua/documents/technic-sdk/7-11/dobavlenie-vych…

Адасюк Валерий Викторович,

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

Никульшина Алёна,

Если я правильно понял, то у вас необходимо отображать общую стоимость всех продуктов, которые привязаны к счету. В этом случае вам надо добавить поле к счету для хранения общей стоимости и обновлять его значение каждый раз, когда происходит изменения по продуктам в детали. И уже значение этого поля отображать в реестре секции по счетам. А вот как "правильно" обновлять такой тотал - это вопрос к бизнес логике. Это может быть в момент изменения перечня продуктов в самой детали и отталкиваться от прайса на момент изменения в самой детали. Либо это может быть некий бизнес процесс, который будет производить перерасчеты и изменять тотал в счетах. Например, когда вы решили изменить прайс по продукту и хотите, чтобы во всех счетах, которые неоплачены в течение трех дней, произвелись перерасчеты стоимости по каждому продукту и соответственно тотал по счету.

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

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

 

Никульшина Алёна,

У вас БП отрабатывает асинхронно и после его выполнения (т.е. в callback) надо кидать событие. На карточке редактирования ловить это событие и применять обновление по общей суммы. Еще, как вариант, в определении детали на странице редактирования сделать подписку на изменения детали и там уже отрабатывать БП, а внутри callback вызова БП обновлять значение общей суммы.

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

Народ помогите:

Когда тыкаешь в реестре на лида, высвечиваются кнопки "Открыть","Копировать" ..... и "Квалификацировать".

С удалением кнопок отличных от квалификации проблем не возникло:

                    {

                       "operation": "remove",

                       "name": "DataGridActiveRowCopyAction"// это название из BaseSectionV2

                    }, 

Затык с кнопкой "Квалифицировать"

1) Не понимаю как она называется?

В BaseSectionV2 - я ее не нашел

В моем замещающем разделе LeadSection, есть QualificationProcessButton, но это кнопка в заголовке режима редактирования лида.

 

Нравится

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

Все, подсказали

Название кнопки "DataGridActiveRowQualificationProcessAction"

Последовский Роман,

Я зачищал кнопки в реестре кодом примерно таким образом:

            onRender: function() {

                var grid = this.getCurrentGrid();

                grid.activeRowActions = [];

                this.callParent(arguments);

            }

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

Версия 7.11

Всем привет.

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

Но проблема в следующем:

Если войти в режиме редактирования то отобразится "Красная кнопка" определенная в LeadSectionV2, но если обновить страницу F5, то в режиме редактирования кнопка поменяет свой цвет на синий - т.е кнопка определенная в LeadPageV2.

Встает вопрос: ведь логика обработки при нажатие на кнопку для каждого режима своя.

И пользователь случайно нажав F5, будет дезинформирован

 

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

Нравится

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

"ведь логика обработки при нажатие на кнопку для каждого режима своя."

неа. в секции есть метод onCardAction, при нажатии на кнопку он посылает в карточку сигнал а-ля: "кнопка нажата, у неё такой-то тэг, запусти this[tag]();" Ну и получается такая ситуация: кнопки 2, обработчик 1 (в page схеме)

Ответить

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

Окей обработчик один. А что быть с визуальной состовляющей? Цвета то разные

Последовский Роман пишет:

Цвета то разные

"style": "blue"  в values кнопки принудительно прописать можно

Варфоломеев ДанилаСПСБ

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

Спасибо за разьяснения

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

ServiceDesk 7.11

Добрый день.

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

Нашел ваш ответ за 2015 год, в котором указано что не умеет, но может за 2 года ситуация изменилась ?

Нравится

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

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

Функциональность push-уведомлений появилась в версии 7.11.0 - https://academy.terrasoft.ru/documents/bpmonline-release-notes#TOC_Моби…

Вильшанский Дмитрий,

не обнаружил в указанное статье информации по push уведомлениям. Поиск по слову push и уведомление не дал результатов.

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

Будьте любезны выслать ссылку конкретнее или процитировать .

Плотников ДИ пишет:

Вильшанский Дмитрий,

не обнаружил в указанное статье информации по push уведомлениям. Поиск по слову push и уведомление не дал результатов.

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

Будьте любезны выслать ссылку конкретнее или процитировать .

По умолчанию уведомления не отображаются в мобильном устройстве.



Push-уведомления необходимо настраивать дополнительный БП, чтобы они отобразились

Вот статья - https://academy.terrasoft.ru/documents/technic-bpms/7-11/kak-nastroit-o…

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

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

 

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

Дано:

1. Имеется Project

2. Имеется собственное поле в объекте Opportunity (пусть будет UsrProject), которое ссылается на проект (тип ессно Lookup по объекту Project)

3. Есть собственный объект, записи которого всегда ссылаются на Opportunity (назовем их даты получения пакетов документов). Содержимое этой сущности не важно.

 

Задача: при отображении связанной сущности Project генерировать правильную ссылку на редактирование Project.

 

Проблема:

Изначально в системе есть две страницы редактирования для сущности Project: ProjectPageV2 и WorkPageV2. Система как-то сама должна определять типа записи и генерировать ссылку либо на ProjectPageV2, либо на WorkPageV2. Я точно помню, что как только я добавил поле UsrProject в Opportunity, то ссылка на связанный проект проставлялась как WorkPageV2, вместо положенной ProjectPageV2. Спустя какое-то время, проблема ушла сама собой (что произошло - загадка). Т.е. сейчас на странице редактирования Opportunity все корректно.

Проблема проявилась в другом месте. Я создал раздел по собственным объектам (см. Дано п.3), где я могу фильтровать эти объекты по нужным мне параметрам. Для нормального вывода настроен Tile View, где выводится информация о связанной Opportunity, через Opportunity выводиться информация об Account и Project. Так вот в этом списке упорно проставляется ссылка на проект через WorkPageV2, вместо положенной проверки на тип записи проекта.

 

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

Нравится

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

Максим, привет.

Тоже разбираюсь с этим вопросом и не совсем понимаю где тебе нужна ссылка на Project. Для детали посмотри метод AddColumLink, он как раз и формирует ссылку на соответствующую карточку. Он просто смотрит по какому полю отличаются карточки данного объекта и соответственно подставляет нужную карточку. 

Дмитрий, спасибо за отклик.

Смотри, есть объект, назовем его "платежи в оппортьюнити". Для управления наполнением этого объекта существует соответствующая деталь на странице редактирования оппортьюнити.

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

В настройках Tile view для секции добавляются поля из связанных сущностей:

Таким образом я могу видеть проект в секции, но ссылка ведет всегда на WorkPageV2 без разбора типа записи:

Этот проект точно имеет типа записи Project, а не Project task, но ссылка сгенерирована так, будто это таска в проекте.

 

Максим, привет.

У меня на проекте тоже используются Проекты и Работы, попробовал у себя сделать так же как ты показал - у меня всё отрабатывает как надо. Попробуй поотлаживать addColumnLink - возможно у тебя что-то не так в БД.

Добрый день, соглашусь с Максимом, все ссылки в гриде генерируется в методе addColumnLink из GridUtilitiesV2. Бывают случаи, что некорректно отрабатывает клик на ссылку, хотя ссылка сформирована верно. Но в вашем случае (если верить скриншоту) ошибка в самой ссылке. Без отладки сложно сказать что могло пойти не так.

Разобрался с данной проблемой. Как правильно замечено выше, обработкой занимается addColumnLink, которая в свою очередь вызывает createLink (либо собственный из GridUtilities, либо из LinkColumnHelper). Вся проблематика сводится к тому, что item грида (т.е. по факту строчка грида) ничего не знает про ProjectEntryType, поскольку это значение не подтягивается в item при простом добавлении колонки Project.

Код вычитывает из item значение примерно так:

var type = this.get(columnPath + "." + attribute) || this.get(attribute);
var typeId = type ? type.value : type;

Тут есть несколько вариантов решения проблемы:

1. Добавить на грид вывод соответствующего ProjectEntryType, тогда штатный код все прекрасно найдет и прочитает

2. В коде схемы страницы секции (ну, или детали, если грид рисуется в детали) сделать явное проставление атрибута, чтобы форсировать тип проекта. Минус в данном случае - нет определения типа записи проекта и форсируется конкретная страница редактирования. Для однородных данных этого в принципе достаточно.

Код примерно такой получился:

addColumnLink: function(item, column) {
	var referenceSchemaName = column.referenceSchemaName;
	if (referenceSchemaName === "Project") {
		item.set("ProjectEntryType", {value: "6b4928d7-456a-4acd-a863-3361d46b7649"});
	}
	this.callParent([item, column]);
},

3. В коде схемы (как в варианте выше) делать вычитывание типа проекта из базы и проставлять соответствующий атрибут для item

 

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

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

Коллеги, добрый день!

Возник вопрос, записывается ли в систему факт прохождения/нарушения верификации чек-ина?

Вот есть системная настройка "Радиус верификации чек-ина", в которой указываем, например значение "100" (метров).

На визите выполняем действие "Чек-ин", находясь к 500 метрах от контрагента. Система выдает сообщение о том, что "Верификация не пройдена. Сохранить результаты?".

Если выбрать вариант "Да", то где фиксируется так скажем "нарушение", факт того, что при выполнении действия верификация была нарушена?



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

Нравится

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

Владимир, здравствуйте!

Есть справочная колонка "Статус верификации чекина" - аналитику можно построить по ней. 

Пример описан в Академии - https://academy.terrasoft.ru/documents/sales-enterprise/7-11/kak-kontrolirovat-vypolnenie-chek-ina

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

В 7.11 добавлен фукнционал Artificial Intelligence. Ни где не могу найти справочной информации по запуску функционала в работу. Какие предварителньые настройки необходимо произвести ? Когда и функционал начинает работу?

 

P.S. почему в карточке добавления поста, на данном сайте, отсутсвует версия 7.11 ?

 

Нравится

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

Добрый день.

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

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. Но я могу и ошибаться.

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



необходимо запускать процесс по факту создания обращения по определенному сервису, но внутри процесса необходимо запустить задачу в определенное время ( 17:30 )

Для этого используется таймер. Но необходимо знать количество секунд с момента создания обращения до наступления 17:30.

для этого используем параметр

Param1730 тип данных = дата/время со значением

new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 17, 30, 00)

и параметр

TimerSeconds с типом данных целое число

и в элементе процесса формула ставим

Convert.ToInt32(([#Param1730#]-[#читать дату регистрации и ответственного.Первый элемент результирующей коллекции.Дата регистрации#]).TotalSeconds)

в результате чего процесс падает в ошибку следующего содержания

System.InvalidOperationException: Невозможно вычислить выражение "Convert.ToInt32(([#[IsOwnerSchema:false].[IsSchema:false].[Parameter:{1cf823a2-c792-4b49-ad65-1c06d4b8a9d1}]#]-[#[IsOwnerSchema:false].[IsSchema:false].[Element:{b29f58a2-4656-455f-90b2-ea2c273b142c}].[Parameter:{7344cb74-63fc-4ff0-88c2-2dfffa25a210}].[EntityColumn:{c91a9a6f-008d-4b2e-83d5-03868ad68c99}]#]).TotalSeconds)", ошибка: Адресат вызова создал исключение. ---> System.Reflection.TargetInvocationException: Адресат вызова создал исключение. ---> System.OverflowException: Значение было недопустимо малым или недопустимо большим для Int32.

   в System.Convert.ToInt32(Double value)

   в lambda_method(Closure )

   --- Конец трассировки внутреннего стека исключений ---

   в System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)

   в System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)

   в System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)

   в Terrasoft.Core.ScriptEngine.DynamicExpressoEngine.Eval(String expression, Type resultType)

   в Terrasoft.Core.Process.ProcessParameterValueProvider.EvalExpression(String expressionText, Type resultType)

   --- Конец трассировки внутреннего стека исключений ---

   в Terrasoft.Core.Process.ProcessParameterValueProvider.EvalExpression(String expressionText, Type resultType)

   в Terrasoft.Core.Process.ProcessParametersDataReader.GetValue(Type valueType)

   в Terrasoft.Core.Process.ProcessScriptTask.SetParameterValue(ProcessExecutingContext context)

   в Terrasoft.Core.Process.ProcessFlowElement.Execute(ProcessExecutingContext context)

В чем может быть причина? Время запуска меньше чем 17:30 , кстати если будет время больше 17:30 то как себя поведет таймер? Взять по модулю?

Может кто-то решал аналогичную задачу ?

Нравится

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

Добрый день.

Судя по приведенной ошибке, Вы инициализируете значение параметра timerSeconds  прямо на вкладке параметры процесса. Инициализация параметров происходит в момент запуска процесса, из-за чего в параметр подставляется значение, когда дата регистрации еще не заполнена. Необходимо использовать элемент Формула после чтения данных, и в его рамках подставлять значение в параметр.

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

Всем доброго времени суток. Версия 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); чтобы вывести задачи всех сотрудников

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