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

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

Ситуация:

1) Скачали дополнение

https://marketplace.terrasoft.ru/app/advanced-excel-reports-creatio

Успешно установили его, без ошибок в логах

2) Пробуем вывести раздел на любое рабочее место и получаем ошибку

https://www.screencast.com/t/7Go9Bu2S

Генерация исходных кодов, компиляция, повторная установка, обновление структуры - БД, вообщем классика не помогает.

 

Такая же история с некоторыми другими дополнениями.

Есть ли какое-то решение или информация о причине ошибки?

Буду благодарен за любую информацию!

Нравится

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

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

 

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

 

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

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

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



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

 

Кейс: 

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

 

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

Необходимо, чтобы контакты отображались даже когда строка неактивна, то есть также, как данные других колонок (всегда).

Обычным способом такую колонку добавить не получается.

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

Если есть варианты, как реализовать этот кейс другим путем, буду рад их рассмотреть.

Заранее спасибо за помощь!

 

Нравится

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

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

Дмитрий Анисько пишет:

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

Лучше всего именно так. На уровне встроенного БП объекта детали или отдельным БП заполнять новое текстовое поле в объекте раздела. Можно ещё триггером в базе, но это Вам не подойдёт.

Дмитрий Анисько пишет:

Может быть Вы знаете, как можно добавить колонку в реестр именно на этапе формирования вью-модели?

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

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

 

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

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

1. Добавляем view с 2 колонками - Guid и string. Средствами sql формируем запрос, который в первую колонку будет возвращать Id контрагента, во вторую все "склеенные" в одну строку имена относящихся к нему контактов

2. В контрагенте добавляем колонку-справочник на нашу view (не забываем про галочку контроля целосности)

3. На событии OnInserting контрагента копируем значение колонки Id в колонку из п.2

4. Дальше пользуемся базовой настройкой колонок

 

Манипуляции из пп. 2-3 нужны для того, чтобы сохранить прямую связь

Лопатин Константин,



Большое спасибо за ответ, но указанный способ не подходит.

Нужно сохранить поддержку всех 3-х субд, а создавать View для каждой - не очень удобно. Да и если идти подобным путем, то на мой взгляд проще добавить строковое поле в объект Контрагент и обновлять его на все нужные события для поддержания актуальности данных.

 

Может быть Вы знаете, как можно добавить колонку в реестр именно на этапе формирования вью-модели? Может вы знаете, что можно попробовать переопределить, чтобы изменить стандартное поведение?

 

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

Дмитрий Анисько пишет:

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

Лучше всего именно так. На уровне встроенного БП объекта детали или отдельным БП заполнять новое текстовое поле в объекте раздела. Можно ещё триггером в базе, но это Вам не подойдёт.

Дмитрий Анисько пишет:

Может быть Вы знаете, как можно добавить колонку в реестр именно на этапе формирования вью-модели?

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

Коллеги, большое спасибо за ответы.

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

Дмитрий Анисько пишет:

Коллеги, большое спасибо за ответы.

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

Дело, конечно же, Ваше, но я, если честно, так и не понял каким образом уменьшится нагрузка на БД если сравнивать view и обновление колонки после каждого чиха на событийном слое

 

Нужно сохранить поддержку всех 3-х субд, а создавать View для каждой - не очень удобно

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

Лопатин Константин пишет:

Дело, конечно же, Ваше, но я, если честно, так и не понял каким образом уменьшится нагрузка на БД если сравнивать view и обновление колонки после каждого чиха на событийном слое

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

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

Начал делать отчет в FastReport и столкнулся с отсутствием примеров отчетов. Где взять хороший пример отчета? например, если нужно вывести не просто деталь контакта, а сложный SQL-запрос, настроить видимость полей в зависимости от значения других полей.

Тот пример что в системе - "Полнота наполнения данными (пример)" - не работает

Нравится

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

У террасофта была проблема с этим сервисом до версии 7.16, делал работал как-то с fastreport'ом, делал запрос с подзапросом, точнее, фильтр с подфильтром, с передачей коллекции в другой метод, чтобы создать другую коллекцию.

Данный код функционировал исправно.

https://drive.google.com/drive/folders/1HzJRIJYDW1cbzP3jHPX4w4nswJNXPwEl?usp=sharing 

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

У террасофта была проблема с этим сервисом до версии 7.16, делал работал как-то с fastreport'ом, делал запрос с подзапросом, точнее, фильтр с подфильтром, с передачей коллекции в другой метод, чтобы создать другую коллекцию.

Данный код функционировал исправно.

https://drive.google.com/drive/folders/1HzJRIJYDW1cbzP3jHPX4w4nswJNXPwEl?usp=sharing 

Начал делать отчет в FastReport и столкнулся с отсутствием примеров отчетов. Где взять хороший пример отчета?

 В версии 7.16.1 пишут, что добавлен пример отчета «Знаменательные события контакта», который можно брать за основу при разработке собственных отчетов FastReport. Также в академии есть пример создания отчёта.

например, если нужно вывести не просто деталь контакта, а сложный SQL-запрос

Если именно свой SQL-запрос, то напрашивается создание view и объекта по нему.

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

Добрый день ! Необходимо включить логирование текстов sql - запросов, генерируемых Entity Framework при вызове одного метода кастомного класса, для локализации низкой производительности операции. Подскажите, существует ли такая возможность

Creatio 7.14.3.1686

PostgreSQL 12.2 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39), 64-bit

Нравится

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

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

 

Нам неизвестны никакие юзабельные инструменты кроме встроенных возможностей PostgreSql, описанных тут: https://www.postgresql.org/docs/12/runtime-config-logging.html

Пока единственная альтернатива – включение в web.config в секции db general флажка EnbaleSqlLog, после чего в лог будут падать все запросы, удовлетворяющие условию Threshold. Пример:

  <general connectionStringName="db" securityEngineType="Terrasoft.DB.MSSql.MSSqlSecurityEngine, Terrasoft.DB.MSSql" executorType="Terrasoft.DB.MSSql.MSSqlExecutor, Terrasoft.DB.MSSql" engineType="Terrasoft.DB.MSSql.MSSqlEngine, Terrasoft.DB.MSSql" metaEngineType="Terrasoft.DB.MSSql.MSSqlMetaEngine, Terrasoft.DB.MSSql" metaScriptType="Terrasoft.DB.MSSql.MSSqlMetaScript, Terrasoft.DB.MSSql" typeConverterType="Terrasoft.DB.MSSql.MSSqlTypeConverter, Terrasoft.DB.MSSql" enableRetryDBOperations="false" retryDBOperationFactoryType="Terrasoft.DB.MSSql.MSSqlRetryOperationFactory, Terrasoft.DB.MSSql" binaryPackageSize="1048576" currentSchemaName="dbo" enableSqlLog="true" sqlLogQueryTimeElapsedThreshold="5000" sqlLogRowsThreshold="100" useOrderNullsPosition="false" maxEntitySchemaNameLength="30" />

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

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

Добрый день!

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

Нравится

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

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

 

Если Вы имеете в виду прямо в XLSX-файле выводить информацию о фильтре, то надо дорабатывать логику функции PrepareExport в схеме ExportToExcelService:

/// <summary>
/// Creates and writes excel stream to local storage and return export key.
/// </summary>
/// <param name="esqSerialized">Serialized export esq.</param>
/// <returns><see cref="ExportToExcelResponse"/>.</returns>
public virtual ExportToExcelResponse PrepareExport(string esqSerialized) {
	esqSerialized.CheckArgumentNull("ExportToExcelService.PrepareExport esqSerialized");
	UserConnection.CheckArgumentNull("ExportToExcelService UserConnection");
	UserConnection.DBSecurityEngine.CheckCanExecuteOperation(CanExportGridOperationCode);
	var selectQuery = Json.Deserialize<SelectQuery>(esqSerialized);
	selectQuery.CheckArgumentNull("ExportToExcelService.PrepareExport deserialized SelectQuery");
	var entitySchemaQuery = selectQuery.BuildEsq(UserConnection);
	entitySchemaQuery.CheckArgumentNull("ExportToExcelService.PrepareExport entitySchemaQuery");
	entitySchemaQuery = RemoveBinaryColumnsFromQuery(entitySchemaQuery);
	ExcelConverter.BatchSize = BatchSize;
	var excelData = ExcelConverter.GetExcelData(entitySchemaQuery, UserConnection);
	var storableExcelStream = new StorableStreamEntity { Data = excelData };
	var id = StreamRepository.Create(storableExcelStream);
	return new ExportToExcelResponse {
		Key = id.ToString(),
		Count = ExcelConverter.ExportedRowCount
	};
}

Или, скорее,  вызываемую из неё GetExcelData в схеме ExcelConverter:

/// <summary>
/// Returns excel data by entity schema query.
/// </summary>
/// <param name="entitySchemaQuery">Export data entity schema query.</param>
/// <param name="userConnection">User connection.</param>
/// <returns>Excel data bytes.</returns>
public virtual byte[] GetExcelData(EntitySchemaQuery entitySchemaQuery, UserConnection userConnection) {
	entitySchemaQuery.CheckArgumentNull("ExcelConverter.GetExcelData entitySchemaQuery");
	userConnection.CheckArgumentNull("ExcelConverter.GetExcelData userConnection");
	_isPrimaryColumnSelected = IsPrimaryColumnSelected(entitySchemaQuery);
	if (!_isPrimaryColumnSelected) {
		entitySchemaQuery.PrimaryQueryColumn.IsAlwaysSelect = true;
	}
	using (var excelStream = new MemoryStream()) {
		try {
			var spreadsheetDocument = CreateExcelFile(excelStream, entitySchemaQuery);
			SaveHeader(entitySchemaQuery);
			SaveData(entitySchemaQuery, userConnection);
			CloseExcelFile(spreadsheetDocument);
		} catch (Exception exception) {
			Log.Error($"Error during export to excel {exception}");
			throw new ExportToExcelException(exception);
		}
		return excelStream.ToArray();
	}
}

 Сейчас сериализованный ESQ с фильтром и набором колонок передаётся в первую в текстовом параметре в виде наподобие:

esqSerialized: "{"rootSchemaName":"Opportunity","operationType":0,"includeProcessExecutionData":true,"filters":{"items":{"4d035dfe-121a-4ac7-a729-353f872bf977":{"items":{"FixedFilters":{"items":{},"logicalOperation":0,"isEnabled":true,"filterType":6}},"logicalOperation":0,"isEnabled":true,"filterType":6}},"logicalOperation":0,"isEnabled":true,"filterType":6},"columns":{"items":{"Title":{"caption":"Название","orderDirection":0,"orderPosition":-1,"isVisible":true,"expression":{"expressionType":0,"columnPath":"Title"}},"Mood":{"caption":"Настроение","orderDirection":0,"orderPosition":-1,"isVisible":true,"expression":{"expressionType":0,"columnPath":"Mood"}},"Account":{"caption":"Контрагент","orderDirection":0,"orderPosition":-1,"isVisible":true,"expression":{"expressionType":0,"columnPath":"Account"}},"Contact":{"caption":"Контакт","orderDirection":0,"orderPosition":-1,"isVisible":true,"expression":{"expressionType":0,"columnPath":"Contact"}},"Stage":{"caption":"Стадия","orderDirection":0,"orderPosition":-1,"isVisible":true,"expression":{"expressionType":0,"columnPath":"Stage"}},"Owner":{"caption":"Ответственный","orderDirection":0,"orderPosition":-1,"isVisible":true,"expression":{"expressionType":0,"columnPath":"Owner"}},"Amount":{"caption":"Сумма продажи","orderDirection":0,"orderPosition":-1,"isVisible":true,"expression":{"expressionType":0,"columnPath":"Amount"}}}},"isDistinct":false,"rowCount":-1,"rowsOffset":-1,"isPageable":false,"allColumns":false,"useLocalization":true,"useRecordDeactivation":false,"serverESQCacheParameters":{"cacheLevel":0,"cacheGroup":"","cacheItemName":""},"queryOptimize":false,"useMetrics":false,"querySource":0,"ignoreDisplayValues":false,"isHierarchical":false}"

А во вторую — в виде обычной ESQ.

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

Добрый день!

 

Подскажите, возможно ли добавить поле в организационные роли рядом с полем название (см. вложение).

 

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

Заранее спасибо

Нравится

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

Попробуйте заместить схему SysAdminUnitPageV2 и там добавить кодом нужное поле.

Сидоров Александр Валерьевич пишет:

Попробуйте заместить схему SysAdminUnitPageV2 и там добавить кодом нужное поле.

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

Эта схема унаследована от SysAdminUnitRoleBasePageV2, поле Name задано в ней:

{
	"operation": "insert",
	"parentName": "Header",
	"propertyName": "items",
	"name": "Name",
	"values": {
		"layout": {"column": 0, "row": 0, "colSpan": 24}
	}
},

 

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

Добрый день!

 

Удалось добавить новое поле на эту страницу. Cоздал замещающий объект SysAdminUnit, в который добавил новую колонку. После этого создал замещающую страницу от SysAdminUnitRoleBasePageV2 и добавил рядом с полем Name новое поле, но теперь проблема в том, что поле не сохраняется. Не подскажете, что я упустил?

Сохранение в SysAdminUnit происходит не тем стандартным способом, как в любой объект, а специальным веб-сервисом /0/rest/AdministrationService/SaveRole. Посмотрите, какие запросы идут из браузера на сервер при сохранении карточки роли, увидите. Видимо, потребуется доработать и логику вызова, и сам сервис, добавив нужное поле.

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

Спасибо!

На демо версии (on-site) возможно редактирование данного сервиса?

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

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

Добрый день! При формировании такой структуры получаю NotSupportedException(внутри None):

 

{
    "QueryType": 1,
    "IsForceUpdate": false,
    "IsUpsert": false,
    "Filters": {
        "RootSchemaName": null,
        "FilterType": 0,
        "ComparisonType": 0,
        "LogicalOperation": 0,
        "IsNull": true,
        "IsEnabled": true,
        "IsNot": false,
        "SubFilters": null,
        "Items": {
            "primaryColumnFilter": {
                "FilterType": 1,
                "ComparisonType": 3,
                "LogicalOperation": 0,
                "IsNull": true,
                "IsEnabled": true,
                "IsNot": false,
                "SubFilters": null,
                "Items": null,
                "LeftExpression": {
                    "ExpressionType": 1,
                    "ColumnPath": null,
                    "Parameter": null,
                    "FunctionType": 1,
                    "MacrosType": 34,
                    "FunctionArgument": null,
                    "DatePartType": 0,
                    "AggregationType": 0,
                    "AggregationEvalType": 0,
                    "SubFilters": null
                },
                "RightExpression": {
                    "ExpressionType": 2,
                    "ColumnPath": null,
                    "Parameter": {
                        "DataValueType": 0,
                        "Value": "310ef086-1e11-4290-9c4e-90e78df4d69a",
                        "ArrayValue": null,
                        "ShouldSkipConvertion": false
                    },
                    "FunctionType": 0,
                    "MacrosType": 0,
                    "FunctionArgument": null,
                    "DatePartType": 0,
                    "AggregationType": 0,
                    "AggregationEvalType": 0,
                    "SubFilters": null
                },
                "RightExpressions": null,
                "RightLessExpression": null,
                "RightGreaterExpression": null,
                "TrimDateTimeParameterToDate": false,
                "Key": null,
                "IsAggregative": false,
                "LeftExpressionCaption": null,
                "ReferenceSchemaName": null
            }
        },
        "LeftExpression": null,
        "RightExpression": {
            "ExpressionType": 2,
            "ColumnPath": null,
            "Parameter": {
                "DataValueType": 0,
                "Value": "310ef086-1e11-4290-9c4e-90e78df4d69a",
                "ArrayValue": null,
                "ShouldSkipConvertion": false
            },
            "FunctionType": 0,
            "MacrosType": 0,
            "FunctionArgument": null,
            "DatePartType": 0,
            "AggregationType": 0,
            "AggregationEvalType": 0,
            "SubFilters": null
        },
        "RightExpressions": null,
        "RightLessExpression": null,
        "RightGreaterExpression": null,
        "TrimDateTimeParameterToDate": false,
        "Key": null,
        "IsAggregative": false,
        "LeftExpressionCaption": null,
        "ReferenceSchemaName": null
    },
    "QueryId": null,
    "QueryKind": 0,
    "ColumnValues": {
        "Items": {
            "UsrName": {
                "ExpressionType": 2,
                "ColumnPath": null,
                "Parameter": {
                    "DataValueType": 1,
                    "Value": "name96ae3de9-f90f-46a9-8b57-afeebedd6499",
                    "ArrayValue": null,
                    "ShouldSkipConvertion": false
                },
                "FunctionType": 0,
                "MacrosType": 0,
                "FunctionArgument": null,
                "DatePartType": 0,
                "AggregationType": 0,
                "AggregationEvalType": 0,
                "SubFilters": null
            },
            "UsrSalesFunnelStage": {
                "ExpressionType": 2,
                "ColumnPath": null,
                "Parameter": {
                    "DataValueType": 10,
                    "Value": "d136a6533-ee2b-4b4b-9366-ffe375568691",
                    "ArrayValue": null,
                    "ShouldSkipConvertion": false
                },
                "FunctionType": 0,
                "MacrosType": 0,
                "FunctionArgument": null,
                "DatePartType": 0,
                "AggregationType": 0,
                "AggregationEvalType": 0,
                "SubFilters": null
            },
            "UsrPartnerType": {
                "ExpressionType": 2,
                "ColumnPath": null,
                "Parameter": {
                    "DataValueType": 10,
                    "Value": "4397d6d7-0b95-43e6-9261-d01df863724f",
                    "ArrayValue": null,
                    "ShouldSkipConvertion": false
                },
                "FunctionType": 0,
                "MacrosType": 0,
                "FunctionArgument": null,
                "DatePartType": 0,
                "AggregationType": 0,
                "AggregationEvalType": 0,
                "SubFilters": null
            },
            "Id": {
                "ExpressionType": 2,
                "ColumnPath": null,
                "Parameter": {
                    "DataValueType": 0,
                    "Value": "310ef086-1e11-4290-9c4e-90e78df4d69a",
                    "ArrayValue": null,
                    "ShouldSkipConvertion": false
                },
                "FunctionType": 0,
                "MacrosType": 0,
                "FunctionArgument": null,
                "DatePartType": 0,
                "AggregationType": 0,
                "AggregationEvalType": 0,
                "SubFilters": null
            }
        }
    },
    "RootSchemaName": "UsrPartnersTest",
    "IncludeProcessExecutionData": true
}

все происходит в облаке

Нравится

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

Евгений, а что это за запрос был? Его формировали программно в коде или сгенерировался при работе с клиентской ESQ?

Смущает пустой RootSchemaName сверху, дважды переданный RightExpression с Guid (и третий раз он же как колонка). Я для пробы поменял значение в какой-то карточке, сохранил, у меня запрос к сервису совсем не такой вышел.

 

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

это BaseQuery сериализованный 

Terrasoft.Nui.ServiceModel.DataContract.BaseQuery, я заполнил структуру так (т к в документации нет примера):
var query = new UpdateQuery
            {
                IncludeProcessExecutionData = true,
                RootSchemaName = schemaName,
                ColumnValues = new ColumnValues
                {
                    Items = new Dictionary<string, ColumnExpression>()
                }
            };
 
 query.Filters = new Filters
            {
                RightExpression = new BaseExpression
                {
                    ExpressionType = EntitySchemaQueryExpressionType.Parameter,
                    Parameter = new Terrasoft.Nui.ServiceModel.DataContract.Parameter
                    {
                        DataValueType = DataValueType.Guid,
                        Value = id
                    }
                },
                Items = new Dictionary<string, Filter>
                {
                    {
                        "primaryColumnFilter", new Filter()
                        {
                            FilterType = FilterType.CompareFilter,
                            ComparisonType = FilterComparisonType.Equal,
                            IsEnabled = true,
                            LeftExpression = new BaseExpression
                            {
                                FunctionType = FunctionType.Macros,
                                ExpressionType = EntitySchemaQueryExpressionType.Function,
                                MacrosType = (EntitySchemaQueryMacrosType) 34,
                            },
                            RightExpression = new ColumnExpression
                            {
                                ExpressionType = EntitySchemaQueryExpressionType.Parameter,
                                Parameter = new Terrasoft.Nui.ServiceModel.DataContract.Parameter
                                {
                                    DataValueType = DataValueType.Guid,
                                    Value = id
                                }
                            }
                        }
                    }
                }
            };
 
            foreach (var parameterPair in operation.Parameters)
            {
                var columnExpression = new ColumnExpression
                {
                    ExpressionType = EntitySchemaQueryExpressionType.Parameter,
                    Parameter = new Terrasoft.Nui.ServiceModel.DataContract.Parameter
                    {
                        Value = parameterPair.Value.Value,
                        DataValueType = parameterPair.Value.Type,
                    }
                };
 
                query.ColumnValues.Items.Add(parameterPair.Value.Name, columnExpression);
            }

 

 

 

 

 

 

 

Всё равно не совсем понятно, почему сделали именно так.

Вы делаете внешний софт на C#, работающий с сервисами системы?

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

Если же делаете внутри скриптов БП, то можно просто использовать класс Update.

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

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

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

 

В самой системе при обновлении записи получается совсем не такой запрос, как у Вас. Например, меняю индекс в адресе контакта:

{
   "rootSchemaName":"ContactAddress",
   "operationType":2,
   "includeProcessExecutionData":true,
   "filters":{
      "items":{
         "primaryColumnFilter":{
            "filterType":1,
            "comparisonType":3,
            "isEnabled":true,
            "trimDateTimeParameterToDate":false,
            "leftExpression":{
               "expressionType":1,
               "functionType":1,
               "macrosType":34
            },
            "rightExpression":{
               "expressionType":2,
               "parameter":{
                  "dataValueType":0,
                  "value":"9ce6c7ce-5ae4-df11-971b-001d60e938c6"
               }
            }
         }
      },
      "logicalOperation":0,
      "isEnabled":true,
      "filterType":6
   },
   "columnValues":{
      "items":{
         "Zip":{
            "expressionType":2,
            "parameter":{
               "dataValueType":1,
               "value":"105122"
            }
         }
      }
   },
   "isForceUpdate":false
}

 

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

остальные поля просто выходят в результате стерилизации BaseQuery от Terrasoft. Если его нужно использовать как-то иначе - дайте знать. Не хочется делать свой класс, учитывая что в библиотеке уже есть готовый

Горянин Евгений Юрьевич пишет:

остальные поля просто выходят в результате стерилизации BaseQuery от Terrasoft.

Но Вы же сами написали, что заполняете так. Зачем там два раза  RightExpression и подобное?

 

Может, лучше интеграцию по OData, как тут:

ИЗМЕНЕНИЕ СУЩЕСТВУЮЩЕГО ОБЪЕКТА

public static void UpdateCreatioEntityByOdatetWcfExample()
{
    // Создание контекста приложения Creatio.
    var context = new Creatio(serverUri);
    // Определение метода, который добавляет аутентификационные cookie при создании нового запроса.
    context.SendingRequest += new EventHandler<SendingRequestEventArgs>(OnSendingRequestCookie);
    // Из коллекции контактов выбирается тот, по которому будет изменяться информация.
    var updateContact = context.ContactCollection.Where(c => c.Name.Contains("Test")).First();
    // Изменение свойств выбранного контакта.
    updateContact.Notes = "New updated description for this contact.";
    updateContact.Phone = "123456789";
    // Сохранение изменений в модели данных сервиса.
    context.UpdateObject(updateContact);
    // Сохранение изменений данных в Creatio одним запросом.
    var responces = context.SaveChanges(SaveChangesOptions.Batch);
}

 

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

ну переделывать общий процесс под OData теперь уже нет возможности. с Select и Insert проблем не возникло, нужен какой-то пример на c# с использованием Update

На C# с запросами к данным работают либо через OData (во внешнем софте) либо внутри конфигурации системы через классы EntitySchemaQuery или Select/Insert/Update/Delete.

 

В Вашем случае это какой-то ещё один вариант. Если разобрались с Select и Insert, наверное и Update можно, чтобы в итоге к сервису уходил JSON, аналогичный отправляемому из браузера.

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

Здравствуйте! Установлена Creatio Studio 7.15.4, СУБД PostgreSQL, используем библиотеку EPPlus 4.5.3.3.

При установке аддона получаем ошибки, лог в приложении.

Нужна помощь в устранении конфликта версий библиотеки EPPlus.

Прикрепленные файлы

Нравится

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

Такое значит, что в состав дополнения входит внешняя сборка (dll-файл) более старой версии, чем в систему добавили Вы. Это частый случай. Если самим откатиться до более старой нельзя, нужно связываться с авторами дополнения, чтобы они обновили. А возможно, они уже сделали, просто исправленный пакет ещё не выложили или дают по запросу.

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

Всем привет!

Пытаюсь сделать кастомные фильтры в секции для разных лукапных полей как это сделано в некоторых секциях для дат и для Ответственного (например Активности). Взял за основу стандартные фильтры, но никак не соображу как сделать это для других колонок - такое ощущение, что там всё захардкожено на колонке Owner, хотя в конфиге можно задать свою колонку. Кто-нибудь разбирался с подобным? Буду признателен за подсказки.

П.С.: Припоминаю, что очень давно делал похожее в версии в 7.7 или 7.8, но там всё выглядело немного по другому и это решение скорее всего не подойдет для новой версии.

 

Заранее спасибо.

Нравится

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

А вы попробуйте новое дополнение. Я его как раз тестировал с точки зрения кастомных фильтров - 80% потребностей им решилось https://marketplace.terrasoft.ua/app/custom-filter-constructor-creatio

А вы попробуйте новое дополнение. Я его как раз тестировал с точки зрения кастомных фильтров - 80% потребностей им решилось https://marketplace.terrasoft.ua/app/custom-filter-constructor-creatio

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

Добрый день,

Есть несколько преднастроенных страниц (использую в БП). Необходимо настроить валидацию определенных полей (напр. только цифры).

Пробовала настроить по аналогии с валидацией на странице раздела, но на преднастроенной странице валидация не срабатывает.

Явно, я что-то упускаю срецифическое для преднастроенных страниц? Просьб направить в правильном направлении.

Пример метода, которй я использую:

            setValidationConfig: function() {

               this.addColumnValidator("CrpINN", this.innValidator);

            },

                innValidator: function(value) {

                var invalidMessage = "";

                var isValid = true;

                var number = value || this.get("CrpINN");

                isValid = (Ext.isEmpty(number) ||

                    new RegExp("^[0-9]{8}$").test(number));

                if (!isValid) {

                    invalidMessage = this.get("Resources.Strings.InvalidINNCodeFormat");

                }

                return {

                    invalidMessage: invalidMessage

                };

            },

      

Заранее спасибо.

 

 

Нравится

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

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

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

Вадим Косарев,

 Спасибо! Я обязательно разберусь с зависимостями.

 

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

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

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

 

setValidationConfig: function() {

             this.addColumnValidator("CrpPortalProductRequest1.CrpINN", this.innValidator);

            },

                innValidator: function(value) {

                

                var invalidMessage = "";

                var isValid = true;

                var number = value || this.get("CrpPortalProductRequest1.CrpINN");

            

                isValid = (Ext.isEmpty(number) ||

                    new RegExp("^[0-9]{8}$").test(number));

                if (!isValid) {

                    invalidMessage = this.get("Resources.Strings.InvalidINNCodeFormat");

                }

                return {

                    invalidMessage: invalidMessage

                };

            },

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