Добрый день,подскажите пожалуйста что подробно означает запись (комментарий) рода /* globals Accountfalse */ например на PreviewPage. Заранее спасибо!

Нравится

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

Никита, здравствуйте!

Это служебное сообщение для дизайнера схемы. А именно, предотвращает предупреждение дизайнера при сохранении схемы, что объект Account не определен.

понял,спасибо!

 

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

Добрый день. 

Для интеграции bpm'online с внешней системой планируется разработать библиотеку, подключаемую как dll, и вызываемую через БП. В библиотеке планируется использование стандартных методов работы с данными через ESQ, которые требуют для своей работы UserConnection и AppConnection. Хотелось бы покрыть библиотеку тестами, так что бы можно было отлаживать работу библиотеки и покрыть ее модульными тестами. 

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

Нравится

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

попробовал сам создать и инициализировать AppConnection и UserConnection, ожидаемо пришел к выводу, что они завязаны на множество недокументированных классов, частично статических, частично завязанных через DI, в том числе логирование и т.п., думаю в текущей реализации bpm'online создать UserConnection вне веб приложения практически нереально. Очень жаль, такая реализация не дает полноценно производить разработку со стандартными механизмами доступа к данным, так как отладить или сделать тесты вне веб приложения невозможно.

Nevg,

Есть статья, где описаны рекомендации по созданию unit тестов: https://academy.terrasoft.ru/documents/technic-sdk/7-12/kak-sozdat-unit…

Если необходимо создавать AppConnection и UserConnection для написания unit тестов, то в ядре есть классы TestAppConnection и TestCoreUserConnection, они находятся в Terrasoft.TestFramework.

 

Спасибо, очень похоже на решение моей задачи! Жаль только,  что информации про эти классы чуть меньше чем ноль )))), на той же академии про них не написано ничего (https://academy.terrasoft.ru/search/TestCoreUserConnection). Есть немного на https://academy.terrasoft.ru/api/netcoreapi/7.12.0/index.html#GeneralSD…. У Вас нет случайно еще примера как их правильно использовать? ))

Tsopa,

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

Коллеги, также столкнулся с необходимостью выполнения запросов к БД в NUnit-тестах. Так и не понял, как можно в данном случае прикрутить TestAppConnection, говорит, что not valid in current context. Удалось ли решить проблему? Не поделитесь ли примерами удачного использования TestAppConnection?

Андронов Олег Алексеевич,

Пример мока запросов в БД:

var appConnection = Substitute.For<AppConnection>();
var userConnection = new TestUserConnection(appConnection);
var dbExecutor = Substitute.For<DBExecutor>(userConnection);
// Настраиваем UserConnection для корректной работы без БД
userConnection.DBExecutor = dbExecutor;
userConnection.DBEngine = Substitute.For<DBEngine>();
userConnection.DBTypeConverter = new TestDBTypeConverter();
// Подготавливаем структуру таблицы результата
var testData = new TestData()
    .Structure()
        .AddStringColumn("Code")              // Формируем список колонок результата
        .AddBoolColumn("CanExecute")
    .NewRow("CanManageAdministration", false) // Формируем записи результата
    .NewRow("CanManageData", true);
DataTable dataTable = testData.GetDataTableUseDataStructure();
// Пример №1: Мокаем запрос к БД, который содержит слово "SysAdminOperation" и значение одного из параметров = "CanManageAdministration"
dbExecutor.ExecuteReader(ArgExt.Contains("SysAdminOperation"), ArgExt.ContainsQueryParameterByValue("CanManageAdministration"))
    .Returns(dataTable.CreateDataReader());
// Пример №2: Мокаем запрос к БД, который содержит слово "SysAdminOperation" и любой параметр
dbExecutor.ExecuteReader(ArgExt.Contains("SysAdminOperation"), Arg.Any<QueryParameterCollection>())
    .Returns(dataTable.CreateDataReader());
// Пример №3: Мокаем все запросы к БД с любыми параметрами
dbExecutor.ExecuteReader(Arg.Any<string>(), Arg.Any<QueryParameterCollection>())
    .Returns(dataTable.CreateDataReader());

Структура так же доступна из свойства testData.DataStructure.

Часто таблица результатов с тестовыми данными становится слишком объемной чтобы делать ее вручную. Чтобы не заботиться о ручном формировании структуры выборки рекомендуется использовать метод GetTestDataWithStructure в классе UnitTestUtilities:

Пример использования GetTestDataWithStructure:

/* Следующая строка подготовит экземпляр класса TestData с готовой к наполнению структурой,
 * содержащей колонки из всех схем, что указаны в массиве string [] schemaNames.
 * Условием корректной работы является наличие схем с такими именами в entitySchemaManager.
 */
TestData testData = UnitTestUtilities.GetTestDataWithStructure(entitySchemaManager, "Activity");

Вместо последовательного добавления значений в строку выборки в TestDataStructure существует метод AddRowWithCustomColumnValues для добавления строки со значениями в конкретных колонках в виде Dictionary<string, object>, где ключ - имя колонки, а значение - соответствующее значение в данной колонке, неуказанные значения автоматически будут заполнены как DBNull.Value:

Пример использования AddRowWithCustomColumnValues:

...
var customValues = new Dictionary&lt;string, object&gt; {
    {"Sender", "johndoe@example.com"}
};
testData.DataStructure.AddRowWithCustomColumnValues(customValues);

 

Tsopa,

Спасибо за такой подробный ответ!

Я правильно понимаю, что в тестировании не получится делать запросы в реальную базу? То есть мы можем удобно и быстро создавать моки и наполнять их данными, после чего делать к ним запросы из тестов так же, как делает боевой метод, но это все равно будет запрос к тестовой структуре, а не к реальной базе? 

Пример: есть условный сервис, который создает обращение. Я могу сделать в [Test] методе запрос к этому сервису обычным WebHttpRequest, проверить, что он отвечает, и отвечает так, как должен. Но в данном случае я не могу быть уверен, что обращение действительно создалось в базе. Возможно, я хотел бы проверить, что в нем произошли некоторые изменения, которые предусмотрены логикой создания записи и т.д. Как можно решить эту задачу?

 

Андронов Олег Алексеевич,

Проверка SqlText, вычитки данных или конвертацию типов, которые зависят от конкретной СУБД

Тест на проверку SqlText, вычитанных из базы данных или конвертацию типов, которые зависят от конкретной СУБД

Описание:

Тест следует располагать в проектах Terrasoft.DB.Oracle.Tests и Terrasoft.DB.MSSql.Tests, если реализация теста отличается для конкретной СУБД. Тест необходимо реализовать для каждой СУБД.

Чаще всего, таким образом, реализуются тесты на проверку SqlText, вычитанных из базы данных или конвертацию типов которые зависят от конкретной СУБД.

Наследуется от:

MSSqlBaseDBTestCase или OracleBaseDBTestCase

Доступно:

Все методы и свойства, описанные в п. 1) и 2) наследованные от классов BaseCommonTestCase, BaseCoreTestCase и BaseDBTestCase, но перегружают методы возвращающие типы определенные для конкретной СУБД.

DBEngine CreateDBEngine()

DBSecurityEngine CreateDBSecurityEngine()

DBMetaScript CreateDBMetaScript(UserConnection userConnection)

DBMetaEngine CreateDBMetaEngine(UserConnection userConnection)

DBExecutor CreateDBExecutor(UserConnection userConnection)

Пример:

Константа типа DateTime собирается для Oracle и для MSSql по разному. Поэтому реализуем тест для двух СУБД

// Тест для MSSql
// Тестируется как собирается Sql для константы типа DateTime
[Test, Category("PreCommit")]
public void GetSqlText_ReturnCorrectSqlText_UseDataTimeParameter() {
        // Создаем экземпляр MSSqlEngine
        var dbEngine = CreateDBEngine();
        // Создаем пустой и легкий UserConnection без ненужных нам инициализаций
        var currentConnection = CreateEmptyUserConnection();
        // Самостоятельно задаем DBEngine для экземпляра UserConnection
        currentConnection.DBEngine = dbEngine;
        var dateTimeValue = new DateTime(1900, 2, 3, 4, 5, 6, 7);
        var select =
                new Select(currentConnection)
                        .Column(Column.Const(dateTimeValue))
                .From("City");
        string sqlText = select.GetSqlText();
        string testSqlText =
                "\nSELECT" +
                        "\n\tCONVERT(DATETIME, '1900-02-03 04:05:06.007', 121)" +
                "\nFROM" +
                        "\n\t[dbo].[City]";
        Assert.AreEqual(testSqlText, sqlText);
}
 
// Тест для Oracle
// Тестируется как собирается Sql для константы типа DateTime
[Test, Category("PreCommit")]
public void GetSqlText_ReturnCorrectSqlText_UseDataTimeConstant() {
        // Создаем экземпляр OracleEngine
        var dbEngine = CreateDBEngine();
        // Создаем пустой и легкий UserConnection без ненужных нам инициализаций
        var currentConnection = CreateEmptyUserConnection();
        // Самостоятельно задаем DBEngine для экземпляра UserConnection
        currentConnection.DBEngine = dbEngine;
        DateTime dateTimeValue = new DateTime(1900, 2, 3, 4, 5, 6, 7);
        Select select =
                new Select(currentConnection)
                        .Column(Column.Const(dateTimeValue))
                .From("City");
        string sqlText = select.GetSqlText();
        string testSqlText =
                "\nSELECT" +
                        "\n\tTO_TIMESTAMP('1900-02-03 04:05:06.007', 'YYYY-MM-DD HH24:MI:SS.FF3')" +
                "\nFROM" +
                        "\n\t\"TEST\".\"City\"";
        Assert.AreEqual(testSqlText, sqlText);
}

 

Где взять методы: CreateDBEngine(), CreateEmptyUserConnection()?

Tsopa,

System.TypeInitializationException: 'The type initializer for 'NSubstitute.Core.SubstitutionContext' threw an exception.'

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

Можно ли каким-то образом построить такой запрос на клиенте:

update KitTrackingInformation

set

    TrackingNumber = @TrackingNumber

from KitTrackingInformation

        join BTSample on BTSample.BTKitIDLookupId = KitTrackingInformation.KitId

            join BTSampInShipment on BTSampInShipment.BTSampleIDId = BTSample.Id

where SampInShipment.BTShipmentId = @ShipmentId

Понятно, что это будет выглядеть приблизительно так:

                    var updateTrackingInfo = Ext.create("Terrasoft.UpdateQuery", {

                        rootSchemaName: "KitTrackingInformation"

                    });

                    updateTrackingInfo.setParameterValue("TrackingNumber", trackingNumber,

                        Terrasoft.DataValueType.SHORT_TEXT);

                                       updateTrackingInfo.filters.addItem(updateTrackingInfo.createColumnFilterWithParameter(

                        this.Terrasoft.ComparisonType.EQUAL,

                        "<путь по связям для фильтрации>", shipmentId));

                    updateTrackingInfo.execute(function(response) {

                        if (response.success) {

                            debugger;

                        }

                    }, this);

Из всего вышеописанного следует 2 вопроса:

1) каким образом построить путь для фильтрации

2) можно ли вообще реализовать UpdateQuery с фильтрацией по полю связанной таблицы

Нравится

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

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

Вот пример даже тройного join-а:

[SysAdminUnit:Contact:Owner].[SysUserInRole:SysUser:Id].[SysAdminUnit:Id:SysRole].Id

Ещё один:

[SysAdminUnit:Contact].[SysUserInRole:SysUser].SysRole

Сработает ли для update, нужно тестировать, глядя на получающиеся запросы в SQL-профайлере.

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

Спасибо за ответ.

А какие sql-запросы получаются в итоге по этим примерам?

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

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

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

Добрый день!

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

В разделе "Продажи" добавил справочное поле созданного раздела "Проект". Необходимо подставить его значение в соответствующее добавленное поле в деталь, при добавлении продукта

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

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

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

 

Нравится

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

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

Это может быть отдельный бизнес-процесс, стартующий по сигналу измнения продажи, встроенный процесс на объекте «Продажа» или даже триггер на уровне SQL-сервера. Первый и последний варианты рассматриваются тут.

на коллбэке в методе onLookupResult открывать (делать переход на) карточку со скрина 3

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

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

Максим, привязываться к интерфейсу не всегда уместно, вдруг поле заполнят по OData, например.

Илья, в таком случае лучше завязать логику БП на создание нового продукта, прописывать там проект из продажи, если ещё не указан. Опять же, либо отдельным БП по сигналу, либо встроенным на объекте «Продукт», либо, в крайнем случае, триггером.

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

Александр, спасибо! Согласен, БП это будет проще всего сделать.

Добрый день.

В Вашем случае можно просто при объявлении детали на странице в атрибуте "defaultValues" указать нужное значение.

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

Вот пример:

            details: /**SCHEMA_DETAILS*/{

                "PatientCardBlock": {

                    "schemaName": "PatientCardBlockSchemaDetail",

                    "entitySchemaName": "PatientCardBlock",

                    "defaultValues": {

                        "Contact": {

                            "masterColumn": "Id"

                        },

                        "DiseaseType": {

                            "masterColumn": "Disease"

                        },

                        "TherapeuticArea": {

                            "masterColumn": "TherapeuticArea"

                        },

                        "BlockType": {

                            "value": "5b64fd0b-20af-4ce6-8c46-b39de8629f13",

                            "displayValue": "Demographics"

                        }

                    },

                    "filterMethod": "demographicsFilter"

                },

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

Алла, спасибо! То что надо)

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

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

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

Добрый день, коллеги.

У нас недавно была внедрена система terrasoft bpmonline которая использует MS SQL. Хотелось бы узнать, есть ли какие-то рекомендованные регламентные процедуры по поддержке этой СУБД. У меня есть относительно большой опыт в поддержке MS SQL для 1С и там к стандартным регламентным процедурам относят перестроение индексов, сбор статистики и очистка процедурного кеша. Эти операции реально помогают производительности 1С. Скажите, имеет ли смысл применять подобные регламентные операции для MS SQL в случае terrasoft bpmonline? Возможно, terrasoft имеет какие-то свои рекомендации (к сожалению, пока не сталкивался с ними) ? Заранее спасибо за ответ.

Нравится

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

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

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

Например, в SysUserSession при каждом входе пользователя или какой-то интеграции пишется новая запись. Если её никогда не чистить, она вырастает до больших размеров и работа с ней замедляется, встречаются deadlock-и. Аналогично, в IntegrationLog пишется информация при работе интеграций, если такие предусмотрены в Вашей системе. Другие подобные таблицы можно увидеть, построив в Management Studio отчёт «Disk Usage by Top Tables».

Плюс в оптимизации стоит учитывать, что в Terrasoft повсеместно используются в качестве первичных ключей GUID-ы.

Иногда объёмы данных столь велики, что для нормального выполнения запросов помогает только переход на SSD, поскольку HDD не справляется. И версию MS SQL лучше выбрать 2016 и новее.

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

 Большое спасибо за Ваш ответ.

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

Добрый день. Подскажите, кто-нибудь уже делал быстрые фильтры, для кастомной детали.

 

Пробовал сделать так, но фильтры на детали не отобразились:

define("UsrScheduleForAllDayDetail", [], function() {
	return {
		entitySchemaName: "UsrScheduleForAllDay",
		messages: {
			/**
			 * @message GetFixedFilter
			 * ######## ######## FixedFilter.
			 * @param {String} ######## #######.
			 * @return {Object} ######.
			 */
			"GetFixedFilter": {
				mode: this.Terrasoft.MessageMode.PTP,
				direction: this.Terrasoft.MessageDirectionType.PUBLISH
			},
		},
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		diff: /**SCHEMA_DIFF*/[
			{
				"operation": "merge",
				"name": "DataGrid",
				"values": {
					"type": "listed",
					"hierarchical": true,
					"sortColumnDirection": { "bindTo": "disableGridSorting" },
					"hierarchicalColumnName": "ParentId",
					"updateExpandHierarchyLevels": {
						"bindTo": "onExpandHierarchyLevels"
					},
					"expandHierarchyLevels": {
						"bindTo": "expandHierarchyLevels"
					}
				}
			},
			{
				"operation": "insert",
				"name": "QuickFilterModuleContainer",
				"parentName": "Detail",
				"propertyName": "items",
				"values": {
					"id": "QuickFilterModuleContainer",
					"selectors": {wrapEl: "#QuickFilterModuleContainer"},
					"itemType": Terrasoft.ViewItemType.CONTAINER,
					"wrapClass": ["quick-filter-module-container-wrapClass"],
					"items": []
				}
			}
		]/**SCHEMA_DIFF*/,
		methods: {
			init: function() {
				this.callParent(arguments);
				this.initFixedFiltersConfig();
			},
			initFixedFiltersConfig: function() {
				var fixedFilterConfig = {
					entitySchema: this.entitySchema,
					filters: [
						{
							name: "PeriodFilter",
							caption: this.get("Resources.Strings.PeriodFilterCaption"),
							dataValueType: this.Terrasoft.DataValueType.DATE,
							startDate: {
								columnName: "UsrDate",
								defValue: this.Terrasoft.startOfWeek(new Date())
							},
							dueDate: {
								columnName: "UsrDate",
								defValue: this.Terrasoft.endOfWeek(new Date())
							}
						}
					]
				};
				this.set("FixedFilterConfig", fixedFilterConfig);
			},

 

Нравится

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

У вас parentName для QuickFilterModuleContainer существует?

Что вообще говорит консоль и отладка?

Золотарев Артем Андреевич пишет:

У вас parentName для QuickFilterModuleContainer существует?

Что вообще говорит консоль и отладка?

 Реализовал деталь в качестве раздела, там же сразу и заработали фильтры

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

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

Например, вот так:

            setLoggerActivatorParameter: function(clinic) {

                var loggerActivatedById;

                if (this.Ext.isEmpty(clinic)) {

                    return loggerActivatedById;

                }

                var esqContact = Ext.create("Terrasoft.EntitySchemaQuery", {

                    rootSchemaName: "Contact"

                });

                var esqAccountFilter = esqContact.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,

                    "Account", clinic.value);

                var esqDataLoggerActivatorFilter =

                    esqContact.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,

                    "DataLoggerActivator", true);

                esqContact.filters.add("esqAccountFilter", esqAccountFilter);

                esqContact.filters.add("esqDataLoggerActivatorFilter", esqDataLoggerActivatorFilter);

                esqContact.getEntityCollection(function(result) {

                    if (result.success && result.collection.getCount()) {

                        loggerActivatedById = result.collection.first().get("Id");

                        return loggerActivatedById;

                    }

                }, this);

            }

Но из-за ассинхроности, пока отработает функция setLoggerActivatorParameter, то запись уже добавится в таблицу без значения поля loggerActivatedById.

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

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

Нравится

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

Из других вариантов:

1) сервис

2) использовать chain на клиенте (реализация гуглится по форуму или тут)

3) кривой, но рабочий (более-менее) способ — делать тот же самый esq только при загрузке страницы, где-нибудь в init-е. Ну и складировать результат в переменную. Потом в обработчике уже к переменной обращаться.

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

Необходимо реализовать автоматическое добавление полей на карточку по определенному условию. То есть не в 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"…)

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

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

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

Формируем запрос к БД через 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");

 

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

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

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

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