7.12
редактируемый грид
динамический грид
sales

Есть потребность сделать реестр который можно редактировать. У реестра нет таблица в БД. Он должен формироваться динамически с разных таблиц. Одна колонка должна быть редактируемая где пользователь будет писать значение. Этот реестр наверно должен быть в отдельном окне. После заполнения пользователь жмет кнопку Ок и БПМ обрабатывает реестр и проделывает работу в исходном коде.

Вопрос: Возможно ли сделать такое окно и если да то куда копать?

Нравится

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

На мой взгляд, Вашу задачу можно решить проще.

1. Создаете представление (view) с нужными Вам данными.

2. На основании представления создаете деталь с обыкновенным нередактируемым реестром. Возможность добавления, редактирования и удаления у детали убираете. Использование обычной детали имеет, как минимум одно преимущество, - возможность настройки колонок из связанных объектов.

3. Над реестром добавляете виртуальное поле и кнопку [OK]. В зависимости от перемещения по детали подтягиваете в виртуальное поле нужное значение соответствующее активной записи. На click кнопки реализуете сохранение введенного пользователем значения в нужную таблицу или таблицы.

Визуально это будет выглядеть приблизительно так.

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

На мой взгляд, Вашу задачу можно решить проще.

1. Создаете представление (view) с нужными Вам данными.

2. На основании представления создаете деталь с обыкновенным нередактируемым реестром. Возможность добавления, редактирования и удаления у детали убираете. Использование обычной детали имеет, как минимум одно преимущество, - возможность настройки колонок из связанных объектов.

3. Над реестром добавляете виртуальное поле и кнопку [OK]. В зависимости от перемещения по детали подтягиваете в виртуальное поле нужное значение соответствующее активной записи. На click кнопки реализуете сохранение введенного пользователем значения в нужную таблицу или таблицы.

Визуально это будет выглядеть приблизительно так.

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

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

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

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

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

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

Если логика реализуемая на уровне БД, то ещё можно и представлением с II, IU, ID-триггерами сделать. А потом с ним работать как с обычной таблицей, привязав к ней схему, а затем делать деталь с редактируемым реестром.

Показать все комментарии
обрабатывающий сигнал
7.12
sales

Нужно запустить БП по событию изменеия: изменение, удаление добавление дня рождения, мобильного телефона, email.

При стандартном "Сигнал" не отслеживает, хотя в таблице изменения вносит

Нравится

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

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

Для решения данной бизнес цели Вам необходимо учитывать что в bpm'online средства связи и знаменательные события это отдельные таблицы, в которые добавляются записи. И в данных таблицах указывается связь с записью контакта.

Необходимо отслеживать изменения записей в отдельных объектах

http://prntscr.com/l62dpt

http://prntscr.com/l62dsn

 

 

 

Показать все комментарии
бизнес-процесс
чтение данных
название
7.12
sales

Можно ли как-то прочитать название если в объекте в колонке указан справочник, так как там указан Guid?

Пример:

[#Читать данные контакта.Первый элемент результирующей коллекции.Страна#] узнать название страны при чтении из "Читать данные"

Нравится

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

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

Можно получить нужное вам значение 2 вариантами.

1. Первый способ - 2-мя элементами 'Чтение данных'. Одним вычитываете Id города из Вашего объекта, а вторым название города по его Id из предыдущего элемента.

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

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

Можно получить нужное вам значение 2 вариантами.

1. Первый способ - 2-мя элементами 'Чтение данных'. Одним вычитываете Id города из Вашего объекта, а вторым название города по его Id из предыдущего элемента.

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

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

Первый способ не подходит, там 18 справочником, выйдет многовато читать. Второй способ я использовал, но руководство не совсем приветствует использование C# скриптов

Придётся делать подряд 2 элемента чтения данных: в первом читать из контакта Id страны, во втором — из справочника стран, отфильтрованного по этому Id, получать название.

Зверев Александр у меня 6 таблиц которые нужно заполнить данными. Для каждой таблицы порядка 20 справочников читать. Выйдет адский труд

Если таких слишком много и писать скрипты не хотите, можно ещё сделать view с текстовыми колонками, потом создать по нему объект и работать с ним.

Prime Source,

Prime Source пишет:

руководство не совсем приветствует использование C# скриптов

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

К сожалению, пока вычитать данные из связанных таблиц в элементе 'Чтение данных' невозможно.

Как вариант, можно реализовать представление, которое содержит все нужные данные и обращаться к нему из элемента 'Чтение данных', но это такой вариант костыля и потом, так как мне не до конца известна Ваша задача, то не факт, что представление будет лучше, чем C# код.

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

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

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

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

Здравствуйте. Для интеграции с существующей системой CRM нужно в трансферную таблицу вложить изменения контрагента и контактов. Контакты берутся из AD. Логины AD хранятся в таблице SysAdminUnit. Проблема в том что через БП добраться так просто к колонке LDAPEntry, нужно написать C# скрипт. Скрипт я написал, он работает

using System;
using System.Collections.Generic;
using System.Linq;
using Terrasoft.Core;
using Terrasoft.Core.Entities;
using CoreConfiguration = Terrasoft.Core.Configuration;

namespace Terrasoft.Configuration.PsADSearchUser
{
	public class PsADSearchUserHelper
	{
		#region Properties: Public

		public UserConnection UserConnection {
			get;
			private set;
		}

		#endregion
		
		#region Constructors: Public

		public PsADSearchUserHelper(UserConnection userConnection) {
			UserConnection = userConnection;
		}

		#endregion

		#region Methods: Public

		public virtual string GetLoginADByContactId(string contactId){
			if (string.IsNullOrEmpty(contactId)) {
				return string.Empty;
			}
			var result = "";
			var esq = new EntitySchemaQuery(UserConnection.EntitySchemaManager, "SysAdminUnit");
			var contact = esq.AddColumn("Contact");
			var colLDAPEntry = esq.AddColumn("LDAPEntry");
			var esqFilter = esq.CreateFilterWithParameters(FilterComparisonType.Equal, "Contact", contactId);
			esq.Filters.Add(esqFilter);
			var entities = esq.GetEntityCollection(UserConnection);
			if (entities.Count > 0)
			{
				//result = entities[0].GetColumnValue(colLDAPEntry.Name).ToString();
				// Также можно использовать такой вариант:
				result = entities[0].GetTypedColumnValue(colLDAPEntry.Name);
			}
			return result;
		}

		#endregion
	}
}

В БП был создан метод

public virtual void LoginADB() {
	var helper = Factories.ClassFactory.Get(new Factories.ConstructorArgument("userConnection", UserConnection));
	LoginADByContact = helper.GetLoginADByContactId(ContactId.ToString());
}

и Using

Terrasoft.Configuration.PsADSearchUser

В "Задание-сценарий" был вызван метод

LoginADB();
return true;

Но при компиляции выдает ошибку

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

 

Нравится

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

1) Непонятно зачем всё это вынесено в метод, а не скрипт таск.

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

var helper = Factories.ClassFactory.Get<PsADSearchUserHelper>(new Factories.ConstructorArgument("userConnection", UserConnection));
var LoginADByContact = helper.GetLoginADByContactId(ContactId.ToString());

то оно даже будет работать. Но на дворе уже 7.13, и галка с интерпретацией нещадно выпилена. Поэтому делаем скрипт-таск со следующим кодом:

//Получаем переменные процесса через Get
var connection = Get<UserConnection>("UserConnection");
var contactId = Get<Guid>("ContactId");

//вызываем метод
//Кстати, а зачем кидать guid как string???
PsADSearchUserHelper helper = new PsADSearchUserHelper(connection);
string LoginADByContact = helper.GetLoginADByContactId(contactId.ToString());

 

1) Получите в скриптаске UserConnection для БП это будет:

UserConnection UserConnection = Get<UserConnection>("UserConnection");

2) Передайте его в ваш класс (лучше через конструктор с параметрами)

Если вы будете дергать ваш класс например из вэб сервиса метод получения UserConnection будет немного другой. Поэтому лучше его передавать в конструкторе класса.

3) Откройте свойства БП перейдите во вкладку методы и там добавьте в USING  Terrasoft.Configuration.PsADSearchUser

4) В методе просто пропишите

//определите ContactId

UserConnection UserConnection = Get<UserConnection>("UserConnection");

var helper = new PsADSearchUserHelper(UserConnection);
var rezult  = helper.GetLoginADByContactId(ContactId.ToString());

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

Удачи

 

 

 

 

Григорий Чех, В свойствах БП прописан USING "Terrasoft.Configuration.PsADSearchUser"

В методе

public virtual void LoginADB(Guid contact) {
	UserConnection UserConnection = Get<UserConnection>("UserConnection");
	var helper = new PsADSearchUserHelper(UserConnection);
	LoginADByContact = helper.GetLoginADByContactId(contact.ToString()); // LoginADByContact уже определен в свойствах как геттер и сеттер, должен быть глобальным но не видит его
}

В "Задание-сценарий" (я так понимаю это скриптаск)

UserConnection UserConnection = Get<UserConnection>("UserConnection"); // Это тут нужно?
LoginADB(ContactId); // Через параметр передать не выходит

Не совсем понял Вас "//определите ContactId".

Видимо что-то не так написал.

1) Непонятно зачем всё это вынесено в метод, а не скрипт таск.

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

var helper = Factories.ClassFactory.Get<PsADSearchUserHelper>(new Factories.ConstructorArgument("userConnection", UserConnection));
var LoginADByContact = helper.GetLoginADByContactId(ContactId.ToString());

то оно даже будет работать. Но на дворе уже 7.13, и галка с интерпретацией нещадно выпилена. Поэтому делаем скрипт-таск со следующим кодом:

//Получаем переменные процесса через Get
var connection = Get<UserConnection>("UserConnection");
var contactId = Get<Guid>("ContactId");

//вызываем метод
//Кстати, а зачем кидать guid как string???
PsADSearchUserHelper helper = new PsADSearchUserHelper(connection);
string LoginADByContact = helper.GetLoginADByContactId(contactId.ToString());

 

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

 

А как теперь найденное значение присвоить свойству LoginADByContact присвоить найденное значение?

Prime Source,

Set("LoginADByContact", LoginADByContact)

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

Я что-то написал и сам потом сообразил. Спасибо большее, просто огромное. ???

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

Подскажите,можно ли виртуальное поле типа LOOKUP сделать выпадающим списком?

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

Нравится

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

Обычно хватает добавить в diff "contentType": Terrasoft.ContentType.ENUM

{
	"operation": "insert",
	"name": "AccountType",
	"parentName": "ProfileContainer",
	"propertyName": "items",
	"values": {
		"bindTo": "Type",
		"layout": {
			"column": 0,
			"row": 2,
			"colSpan": 24
		},
		"contentType": Terrasoft.ContentType.ENUM
	}
},

 

А если не менять данные есть?

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

Обычно хватает добавить в diff "contentType": Terrasoft.ContentType.ENUM

{
	"operation": "insert",
	"name": "AccountType",
	"parentName": "ProfileContainer",
	"propertyName": "items",
	"values": {
		"bindTo": "Type",
		"layout": {
			"column": 0,
			"row": 2,
			"colSpan": 24
		},
		"contentType": Terrasoft.ContentType.ENUM
	}
},

 

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

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

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

Роли хранятся в таблице SysAdminUnit.

Привязка пользователя идет в таблице SysUserInRole где опять же мы получаем SysUserId которая ссылается на SysAdminUnit, где мы получаем ContactId.

Нравится

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

 Что-то наподобие этого в lookuplistconfig прописать

filter: function() {return Terrasoft.createColumnFilterWithParameter(3, "[SysAdminUnit:Contact].[SysUserInRole:SysUser].SysRole.Id", "id группы")}

 

Select * from "Contact" INNER JOIN "SysAdminUnit" ON "Contact"."Id" = "SysAdminUnit"."ContactId"
where "SysAdminUnit"."Id" IN (Select "SysUserId" from "SysUserInRole" where "SysRoleId" = 'Ваша функциональная роль')

 

 Что-то наподобие этого в lookuplistconfig прописать

filter: function() {return Terrasoft.createColumnFilterWithParameter(3, "[SysAdminUnit:Contact].[SysUserInRole:SysUser].SysRole.Id", "id группы")}

 

Варфоломеев Данила пишет:

function() {return Terrasoft.createColumnFilterWithParameter(3, "[SysAdminUnit:Contact].[SysUserInRole:SysUser].SysRole.Id", "id группы")}

Огромное спасибо. 

Показать все комментарии
ReportDesigner
sales
фильтрация
MultiSelect
LookupMultiAddMixin
7.11

Здравствуйте. *bpm'sales

Есть ли возможность реализовать на практике следующее:

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

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

Но при открытии окна выбора открывалось окно Множественного выбора, например как тут

2. Передавать Id выбранных записей в отчет.

Есть идеи?

Нравится

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

Доброе утро. На сколько мне известно в базовой логике данная задача не реализована. Вам надо посмотреть в сторону замещения и расширения модуля ReportFilterModule. На данный момент реализована передача фильтра с помощью фильтрации записей в разделе.

var config = [

          {

                name: 'FormingMethod',

                dataValueType: 'FormingMethod'

            }

]

Доброе утро. На сколько мне известно в базовой логике данная задача не реализована. Вам надо посмотреть в сторону замещения и расширения модуля ReportFilterModule. На данный момент реализована передача фильтра с помощью фильтрации записей в разделе.

var config = [

          {

                name: 'FormingMethod',

                dataValueType: 'FormingMethod'

            }

]

Солонко Олег Иванович,

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

Фильтрация по множественному выбору записей в разделе — это то, что есть сейчас. Подробнее описывал в соседней теме.

Зверев Александр,

 

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

Как вариант, можно смотреть на создание карточки параметров отчёта в интерфейсе 5.Х. Там включение множественного выбора включатся одной галочкой. Но тогда нужно будет разбираться, как данные из 5.Х-карточки передаются в отчёт.

Показать все комментарии
примечание
свойство
7.12
sales

Добрый день! 

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

Подскажите пжлст, какое свойство отвечает за этот параметр?

 

Благодарю!

 

Нравится

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

Насколько понимаю такого свойства нет, но что мешает заместить вам детель и вместо поля примечания вставить свое многострочное поле ввода?

Насколько понимаю такого свойства нет, но что мешает заместить вам детель и вместо поля примечания вставить свое многострочное поле ввода?

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

$(document).bind("DOMNodeInserted", function(e) {
if (e.target.id === "cke_ContactPageV2NotesHtmlEdit-html-edit-textarea") {
	var tabs = Ext.getElementById("ContactPageV2NotesHtmlEdit-html-edit-toolbar");
	
	var elem = Ext.get(tabs.children[9]);
	elem.dom.children[1].className = "t-btn-wrapper t-btn-no-text-padding t-btn-style-default t-btn-pressed";

}
}.bind(this));



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

Показать все комментарии
MultiSelect
sales
FastReport
фильтрация Lookup
7.11

Здравствуйте. Как реализовать в форме отчета, поле выбора несколько значений из справочника и корректно передать/обработать выбранные Id в сам отчет?

При поиске наткнулся на примеры с Ответственным, но там выбор только 1 записи.

Нравится

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

Можно сделать как в стандартных отчётах в разделе, которые вызываются из режима итогов, например, «Data entry compliance» в разделе контрагентов. Для построения отчёта в реестре фильтруют или помечают галочками нужные записи, переключаются в итоги, выбирают этот отчёт, а потом строят по выделенным, по отфильтрованным или по всем:

Схема этого отчёта AccountDataCompletenessReport, привязка таких отчётов к разделам задаётся в таблице SysModuleAnalyticsReport. Для выбора вариантов формирования используется страница BaseReportParameterInModulePageFilter.

Зверев Александр,

это должен быть фильтр по lookup, а не самим записям в реестре.

Можно добавить отчёт именно в тот раздел, записи из которого нужно Вам фильтровать.

Зверев Александр,

суть в том что такого раздела не существует это справочник. Ладно давайте конкретнее. У меня есть раздел Складские документы где ведется учет прихода/ухода Продуктов по складам(справочник) и мне нужно что бы в каком-то  отчете раздела Складские документы было окно выбора несколько складов на каких будет проверяться количество конкретного продукта. Это без проблем можно реализовать в тройке (TS 3) через MultiSelectWindow.

Можно и склады завести разделом. Либо смотреть аналогичные карточки свойств отчётов, где могут быть такие поля множественного выбора. В стандартных отчётах Sales встречаются только обычные справочные.

Показать все комментарии
C#
ESQ
GroupBy
sales
7.11

Здравствуйте. Интересует способ использования "Group By"  в entitySchemaQuery (сервер). При поиске наткнулся на топик - https://community.terrasoft.ru/questions/gruppirovka-v-entityschemaquery , но увы, ссылка с ответом битая. 

Нравится

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

Пример использования на C#, документацию нашел только для клиентских запросов, но по аналогии все понятно

var query = new EntitySchemaQuery(_userConnection.EntitySchemaManager, schemaName);
var columnCount = query.AddColumn(query.CreateAggregationFunction(AggregationTypeStrict.Count, query.PrimaryQueryColumn.Name));
var countEntity = query.GetEntityCollection(UserConnection)[0];
var count = countEntity.GetTypedColumnValue<int>(comnCount.Name);
return count;

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

var esq = new Order(UserConnection);
esq.AddColumn(esq.CreateAggregationFunction(AggregationTypeStrict.Count, "Customer.Name").All());
	esq.AddColumn("Description");
	esq.AddColumn("Name");
	esq.AddColumn("Customer");

Добавит в запрос 

GROUP BY Order.Description, Document.Name, Order.CustomerId, Customer.Name;

 

 

 

 

 

Пример использования на C#, документацию нашел только для клиентских запросов, но по аналогии все понятно

var query = new EntitySchemaQuery(_userConnection.EntitySchemaManager, schemaName);
var columnCount = query.AddColumn(query.CreateAggregationFunction(AggregationTypeStrict.Count, query.PrimaryQueryColumn.Name));
var countEntity = query.GetEntityCollection(UserConnection)[0];
var count = countEntity.GetTypedColumnValue<int>(comnCount.Name);
return count;

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

var esq = new Order(UserConnection);
esq.AddColumn(esq.CreateAggregationFunction(AggregationTypeStrict.Count, "Customer.Name").All());
	esq.AddColumn("Description");
	esq.AddColumn("Name");
	esq.AddColumn("Customer");

Добавит в запрос 

GROUP BY Order.Description, Document.Name, Order.CustomerId, Customer.Name;

 

 

 

 

 

Григорий Чех,

Спасибо большое!

Вот, на всякий случай, и пример серверного кода:

EntitySchema entitySchema = UserConnection.EntitySchemaManager.GetInstanceByName("SysProcessElement");
var query = new EntitySchemaQuery(entitySchema);
EntitySchemaQueryColumn elementUIdColumn = query.AddColumn("SchemaElementUId");
EntitySchemaQueryColumn executeCountColumn = query.AddColumn(query.CreateAggregationFunction(AggregationTypeStrict.Count,
	entitySchema.PrimaryColumn.Name));

EntityCollection entities = query.GetEntityCollection(UserConnection);

 

Зверев Александр,

Я для серверного кода пример и приводил :) От клиентского только документация :)

Вот документация по серверной. Ещё в этом документе есть информация.

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