Добрый день!

Какие изменения в основном приложении синхронизируются с мобильным приложением?
Новые разделы и справочники в мобильное приложение добавились.
После решила попробовать сделать другое изменение согласно данной статьи :
https://academy.terrasoft.ru/documents/technic-sdk/7-8/vydelenie-cvetom-...

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

Нравится

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

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

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

Для реализации в мобильной версии необходимо переопределить логику манифеста мобильного приложения. По умолчанию это MobileApplicationManifestDefaultWorkplace.

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

Подскажите пожалуйста, как можно реализовать передачу PDF документа в "файлы и примечания" раздела по протоколу OData с использованием Http-запросов?

Нравится

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

Добрый день.

Для хранения файлов и ссылок по каждому разделу есть отдельная таблица. Например, для раздела [Обращения] - это CaseFile.
Для загрузки файлов используется сервис FileApiService (метод Upload).
Пример вызова сервиса можно посмотреть на примере детали "Файлы и ссылки" (FileDetailV2).

Добрый день, спасибо за быстрый отклик.
Но как я понимаю FileApiService можно использовать для обработки события upload в самой crm. А задача состояла в обратном: на сайте генерируется pdf файл и необходимо его передать в карточку договора в файлы и примечания.
Разобралась как это сделать с помощью OData. Необходимо сначала создать файл, к примеру в ContractFileCollection, с помощью POST с привязкой к Id договора и с необходимым типом, а потом уже в созданный Id документа в /Data записывать необходимый файл с помощью запроса PUT с Content-Type: application/octet-stream.

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

Добрый день!

А можно ли узнать, кто выдал права доступа на запись - пользователь вручную, создана по умолчанию или добавлена в бизнес-процессе?

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

Нравится

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

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

Права доступа на записи хранятся в таблице Sys[Имя_объекта]Right. Для каждой записи о правах есть колонки создал(CreatedbyID) и Изменил(ModifiedbyID).

"Павел Баштовой" написал:Для каждой записи о правах есть колонки создал(CreatedbyID) и Изменил(ModifiedbyID).

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

"Владимир Соколов" написал:
Павел Баштовой пишет:

Для каждой записи о правах есть колонки создал(CreatedbyID) и Изменил(ModifiedbyID).

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

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

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

Пишу PHP модуль для связи сайта с BPM. Есть какой-нибудь Wysywig редактор для построения SQL запросов? Писать такие запросы вручную это просто утомительно. К тому же не ясно, как проконтролировать скомпилированный запрос и обработанный DataService

{

            "QueryType": 0,
            "Columns": {
                "Items": {
                    "Name": {
                        "OrderDirection": 0,
                        "OrderPosition": 0,
                        "Caption": null,
                        "Expression": {
                            "ExpressionType": 0,
                            "ColumnPath": "Name"
                        }
                    },
                    "OwnerLogin": {
                        "OrderDirection": 0,
                        "OrderPosition": 0,
                        "Caption": null,
                        "Expression": {
                            "ExpressionType": 0,
                            "ColumnPath": "[WSysAccount:Contact:Owner].Login"
                        }
                    }
                }
            },
            "AllColumns": false,
            "IsDistinct": false,
            "RowCount": 1,
            "Filters": {
                "FilterType": 6,
                "ComparisonType": 0,
                "LogicalOperation": 0,
                "IsNull": true,
                "IsEnabled": true,
                "IsNot": false,
                "Items": {
                    "FilterByPhone": {
                        "FilterType": 1,
                        "ComparisonType": 9,
                        "LogicalOperation": 0,
                        "IsNull": true,
                        "IsEnabled": true,
                        "IsNot": false,
                        "LeftExpression": {
                            "ExpressionType": 0,
                            "ColumnPath": "[ContactCommunication:Contact].SearchNumber"
                        },
                        "RightExpression": {
                            "ExpressionType": 2,
                            "ColumnPath": null,
                            "Parameter": {
                                "DataValueType": 1,
                                "Value": "54326672198"
                            }
                        }
                    }
                }
            },
            "RootSchemaName": "Contact",
            "OperationType": 0
}';

Нравится

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

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

Наличие визуального редактора для не предусмотрено. Хочу обратить внимание, что SQL запросы и ESQ запросы - это разные инструменты для получения данных. В отличии от ESQ, SQL запросы не учитывают права пользователя. Таким образом один и тот же запрос, интерпретированный на SQL и ESQ может возвращать разный результат.

Пусть так, а как проконтролировать какой SQL запрос получится из этого запроса? На примитивном запросе с одним условием еще более менее понятно, а вот делаю объединение запроса и привет. Например, хочу эмулировать запрос
SearchNumber in ("54326672198", "54326672197") /* пользователи и через 8ку заносят номера и через +7*/
ну или так SearchNumber="54326672198" or SearchNumber="54326672197"
и всё, не отрабатывает, пробовал и через RightExpressions[] и задавал два Items. В первом случае возвращается всегда error, а во втором случае если искать в первом item "54326672197" находит. если номер во втором item, то соответствий нет.

а уж такие запросы типа select * from dbo where id in (select id from dbo1 where x=y) я понимаю вообще не сделать

Добрый день, Андрей.
Мне кажется, что в Вашем случае значительно лучше подойдут sql view нежели сложные odata запросы. Просто создайте view в базе данных, которая будет Вам возвращать нужную выборку по простому запросу и обращайтесь к ней (view должна быть связана с объектом в конфигурации).
В описанном Вами случае, вьюха будет представлять union таблицы контактов с необходимыми полями и всеми вариантами написания номера. Запрашиваете у вьюхи номер в любом формате - она возвращает нужные данные контакта.
Соответственно, отдельная вьюха под каждую задачу.

Также, ознакомьтесь со статьями
https://academy.terrasoft.ru/documents/technic-sdk/7-9/rabota-s-obektam…
и
https://academy.terrasoft.ru/documents/technic-sdk/7-9/primery-zaprosov…
Чуть более сложные запросы в комбинации со вьюхой позволят построить выборку практически любой сложности.
Опять же, на вьюху можно навесить тригер в БД. Тогда можно вообще кастомные запросы обрабатывать.

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

Раньше я мог сделать фильтр для поиска по всем полям «номер телефона» одновременно. Для этого я выбирал «Средство связи контрагента (по колонке Контрагент)» и ставил параметр «существует». После чего дальше фильтровал по Типу (дополнительный телефон, мобильный и т. п.). Все работало. Сейчас нужно сделать похожий фильтр, но я уже не могу поставить параметр «Существует» для нужного объекта. Система настойчиво предлагает выбрать «Колонку». Не могу понять, что я делаю не так.

Нравится

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

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

В прикрепленном gif файле показано как построить расширенный фильтр для поиска контрагента по номеру телефона.

Спасибо! Упустил этот момент.

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

Во время выполнения запроса:

var select = Ext.create("Terrasoft.EntitySchemaQuery", {
        rootSchemaName: "DimensionCustom"
});
select.addColumn("EntitySchemaUId", "EntitySchemaUId");
var levelColumn = select.addColumn("[ForecastDimensionCustom:DimensionCustom:Id].Level");
levelColumn.orderPosition = 1;
levelColumn.orderDirection = this.Terrasoft.OrderDirection.ASC;
select.addColumn("[ForecastDimensionCustom:DimensionCustom:Id].Id", "ForecastDimensionId");
select.filters.addItem(this.Terrasoft.createColumnFilterWithParameter(
        this.Terrasoft.ComparisonType.EQUAL, "[ForecastDimensionCustom:DimensionCustom:Id].ForecastCustom", forecastId));
select.rowCount = 1;
select.getEntityCollection(function(response) {
        if (response.success) {
                var collection = response.collection;
                if (collection && collection.getCount() > 0) {
                        var item = collection.getItems()[0];
                        if (item) {
                                this.set("EntitySchemaUId", item.get("EntitySchemaUId"));
                                this.set("ForecastDimensionId", item.get("ForecastDimensionId"));
                        }
                        if (callback) {
                                callback.call(this);
                        }
                }
        }
}, this);

Получаю Ошибки при исполнении запроса:

Недопустимое имя столбца "DimensionCustomId".
↵Недопустимое имя столбца "ForecastCustomId

Но я никак не могу понять, откуда такие имена колонок взялись - ведь при построении запроса такие колонки не в одной схеме ESQ не указываются.

PS: Объекты ForecastDimensionCustom и DimensionCustom являются копиями базовых объектов из CoreForecast, см.прикрепленные файлы.

Нравится

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

Здравствуйте, Илья.

Проверьте правильность названия колонок в созданных объектах, а так ж в базе данных. Так же переопубликуйте объекты и обновите структуру базы данных.

Для отладки ошибки будет полезным посмотреть какой запрос отправляется в базу данных при помощи Sql server managment studio или же утилиты fiddler2.

А как можно посмотреть запрос через Sql server managment studio ?

"Севостьянов Илья Сергеевич" написал:

А как можно посмотреть запрос через Sql server managment studio ?


В смысле профайлером :)

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

Здравствуйте, где в коде можно найти логику автоматического изменения даты Окончания Активности при проставлении новой даты Начала. Мне нужно чтобы дата Окончания оставлялась такой, которую установил бизнес процесс, а по факту получается, что автоматически проставляется дата Начала + 3 дня (если мы ставим дату начала на 3 дня раньше чем было).

Нравится

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

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

В базовой логике системы при изменении даты начала новой активности вызывается метод onStartDateChanged, который устанавливает значение в поле "Дата завершение".

Для новых записей интервал - 30 минут.

Для существующих записей интервал составляет разницу между "Датой завершения" и "Датой начала". Эта логика реализована на странице редактирования ActivityPageV2.

Что касается логики "Дата начала + 3 дня" - в базовой версии приложения такого нет. Необходимо выполнить отладку разработанной логики.

"Демьяник Алексей" написал:Для существующих записей интервал составляет разницу между "Датой завершения" и "Датой начала". Эта логика реализована на странице редактирования ActivityPageV2.

Как изменить эту логику? Что бы для существующих записей "дата завершения" не менялась при изменении "даты начала"?

Здравствуйте, Виталий.

Вам стоит смотреть в сторону изменения значения атрибута DifferStartDueDate (именно в нем хранится значение устанавливаемого интервала), который используется в методе onStartDateChanged. По умолчанию данному атрибуту устанавливаются значения в методе setDifferStartDueDate схемы ActivityDatesMixin(UIv2).

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

Добрый день!

Возникла проблема при разворачивании демо версии BPMonline. (версия 7.9.0.1228)

Был поднят сервер IIS с приложением. Проводилась настройка файлов конфигурации согласно инструкции по установке (https://academy.terrasoft.ru/documents/sales-enterprise/7-9/ustanovka-bp...). Веб-сокеты настраивал как в (https://academy.terrasoft.ru/documents/sales-enterprise/7-9/ustanovka-bp...) для windows server 2012.
Удалось попасть в приложение и пройти авторизацию, но часть функционала осталась нерабочей (вкладка "Рабочее место, Дизайнер системы, Профиль пользователя" не отзывается на нажатия).
Консоль выдает следующие ошибки:

Uncaught SyntaxError: Unexpected token

Uncaught TypeError: Cannot read property 'entitySchemaName' of undefined
at i. (ConfigurationBootstrap.js:21591)
at all-combined.js:292
at Object.execCb (require.js:1693)
at Module.check (require.js:881)
at Module. (require.js:1136)
at require.js:134
at require.js:1186
at each (require.js:59)
at Module.emit (require.js:1185)
at Module.check (require.js:936)

user: Supervisor/7f3b869f-34f3-4f20-ab4d-7480a5fdf647
file: http://terrasoft_demo.demo.oim:82/0/Nui/ViewModule.aspx
line: 3
column: 1
message: Uncaught SyntaxError: Unexpected token
date: Tue Dec 27 2016 13:08:43 GMT+0400 (Московское время (зима))
stack: SyntaxError: Unexpected token

WebitelVerto.js:3306 WebSocket connection to 'wss://ru1-webitel-switch.bpmonline.com:8082/' failed: WebSocket opening handshake timed out

Все роли и компоненты указанные в руководстве установлены, протокол Websocket стоит.
Единственным отличием от руководства было то, что при настройке пула приложения не удалось выбрать версию среды ASP.NET 4.0.30319 (он не отображался), пришлось выбрать CLR.NET той же версии.

Не могли бы вы подсказать в чем может быть проблема?

Файлы конфигурации прилагаю.

Нравится

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

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

Это совершенно разные ошибки
Uncaught SyntaxError: Unexpected token <

Uncaught TypeError: Cannot read property 'entitySchemaName' of undefined
at i. (ConfigurationBootstrap.js:21591)
at all-combined.js:292
at Object.execCb (require.js:1693)
at Module.check (require.js:881)
at Module. (require.js:1136)
at require.js:134
at require.js:1186
at each (require.js:59)
at Module.emit (require.js:1185)
at Module.check (require.js:936)

Система не смогла прочитать название схемы. Возникает в следующих случаях:
1) Некорректно замещены конфигурационные схемы. Решение: исправить ошибку.
2) Удалена схема, однако SectionBundleModule не пересобрался. Решение: сохранить произвольную схему в конфигурации (нужно сохранить именно схему, а не процесс или объект).

Для перехода в конфигурацию введите адрес [site]/0/dev

WebitelVerto.js:3306 WebSocket connection to 'wss://ru1-webitel-switch.bpmonline.com:8082/' failed: WebSocket opening handshake timed out - ошибка телефонии. Подключение идет по защищенному каналу (wss), а сайт работает на незащищенном канале http.

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

Здравствуйте, хотел написать свое правило поиска дублей для контактов пример того как сделать взял с академии но во время выполнения скрипта появляется ошибка что переменная @parsedConfig имеет недопустимый тип данных. и еще в таблице ContactDuplicateSearchResult нету поля SysAdminUnitId вместо него идет поле GroupHash. Как изменить скрипт чтобы он заработал? bpm 7.8.0

-- Проверка наличия хранимой процедуры с именем tsp_FindContactDuplicateByNameAndContragent.
IF NOT OBJECT_ID('[dbo].[tsp_FindContactDuplicateByNameAndContragent]') IS NULL
BEGIN
    -- Удаление хранимой процедуры.
    DROP PROCEDURE [dbo].[tsp_FindContactDuplicateByNameAndContragent];
END;
GO
-- Создание хранимой процедуры.
CREATE PROCEDURE [dbo].[tsp_FindContactDuplicateByNameAndContragent] (
    -- Этот табличный параметр передается только в случае сохранения нового контакта.
    -- Содержит данные нового контакта.
    -- В случае запуска процесса глобального поиска дублей переданный параметр не содержит данных.
    @parsedConfig CreatingObjectInfo READONLY,
    -- Уникальный идентификатор пользователя, который запустил поиск дублей.
    @sysAdminUnit UNIQUEIDENTIFIER,
    -- Идентификатор текущего правила из таблицы [ContactDuplicateSearchResult].
    -- Этот идентификатор создается после регистрации правила в системе.
    @ruleId UNIQUEIDENTIFIER
)
AS
BEGIN
    -- Получение количества записей из принимаемой таблицы для определения запуска глобального поиска дублей.
    DECLARE @parsedConfigRowsCount INT = (SELECT COUNT(*) FROM @parsedConfig);
    -- Создание временной таблицы с данными контактов для поиска.
    CREATE TABLE #searchContact (
        [Name] nvarchar(250),
                [AccountId] uniqueidentifier,
        [SortDate] DATETIME
    );
    -- В случае глобального поиска выполняется заполнение временной таблицы данными.
    IF @parsedConfigRowsCount = 0
    BEGIN
        -- Добавление во временную таблицу данных для поиска дублей.
        INSERT INTO #searchContact ([Name], [AccountId],[SortDate])
        -- Запрос на выборку данных контактов.
        SELECT
            -- Выбираются колонки ИНН даты модификации контакта.
            [Name],[AccountId],
            MAX([ModifiedOn])
        FROM [Contact]
        -- Добавляется группировка по полям для возможности использовать проверку на количество.
        GROUP BY [Name],[AccountId]
        -- Таблица заполняется только в случае наличия более одного контакта.
        HAVING COUNT(*) > 1;
    END;
   
    -- Заполнение таблицы результатов.
    INSERT INTO [ContactDuplicateSearchResult] ([ContactId], [GroupId], [RuleId], [SysAdminUnitId])
    SELECT
        -- Идентификатор дубля контакта.
        [vr].[Id],
        -- Формирование номера группы.
        DENSE_RANK() OVER (ORDER BY [vr].[SortDate] DESC, [vr].[Name],[vr].[AccountId]),
        -- Идентификатор правила.
        @ruleId RuleId,
        -- Идентификатор пользователя, под которым запущен процесс поиска дублей.
        @sysAdminUnit
    FROM (
        -- Подзапрос, из которого заполняется таблица дублей.
        SELECT
            -- Идентификатор контакта.
            [v].[Id],
            --ФИО контакта.
            [v].[Name],
           --ИД контрагента.
            [v].[AccountId],
            -- Дата сортировки.
            [r].[SortDate]
        -- Таблицы, из которых берутся данные.
        FROM [Contact] [v], #searchContact r
        -- Правило, по которому определяется, что контакты — дубли.
        WHERE [v].[Name] = [r].[Name] AND [v].[AccountId] = [r].[AccountId]
        -- Группировка результата поиска.
        GROUP BY [v].[Name],[v].[AccountId], [r].[SortDate], [v].[Id]
    ) [vr];
END;
GO

Нравится

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

Здравствуйте, я новичок в системе. Но насколько, я понял, статья https://academy.terrasoft.ru/documents/technic-sdk/7-8/dobavlenie-pravi… с примером справедлива для bpm 7.8.3 и выше... В версии 7.8.0 в таблице DuplicatesRule нет поля "Название процедуры"... Поэтому непонятно, как будет происходить вызов вновь созданной процедуры в 7.8.0, если только изменить DeduplicationSearch...

Здравствуйте,
Правила дедупликации расположены в таблице [DuplicatesRule]
Там же в колонке [ProcedureName] указаны имена хранимых процедур, ответственных за обработку.
Почитайте код любой из данных процедур и напишите свой по аналогии.
К примеру, во вложении, код процедуры [tsp_FindAccountDuplicateByWeb]

new_text_document.txt

Здраствуйте
1. Касательно этого блока:
IF @parsedConfigRowsCount = 0
BEGIN
-- Добавление во временную таблицу данных для поиска дублей.
INSERT INTO #searchContact ([Name], [AccountId],[SortDate])
-- Запрос на выборку данных контактов.
SELECT
-- Выбираются колонки ИНН даты модификации контакта.
[Name],[AccountId],
MAX([ModifiedOn])
FROM [Contact]
-- Добавляется группировка по полям для возможности использовать проверку на количество.
GROUP BY [Name],[AccountId]
-- Таблица заполняется только в случае наличия более одного контакта.
HAVING COUNT(*) > 1;
END;

Я бы сделал как в базовой хранимке:
IF @parsedConfigRowsCount = 0
BEGIN
INSERT INTO #searchAccount ([Name], [SortDate])
SELECT
[dedup].[Name],
MAX([dedup].[SortDate]) [SortDate]
FROM (
SELECT [Id],
[dbo].[fn_NormalizeString]([Name], @validChar) AS [Name],
MAX([ModifiedOn]) [SortDate]
FROM [Account]
GROUP BY [Id], [Name]
) AS [dedup]
GROUP BY [dedup].[Name]
HAVING COUNT(*) > 1;
END;
ELSE
BEGIN
INSERT INTO #searchAccount ([Name], [SortDate])
SELECT
[Name],
GETDATE() AS [SortDate]
FROM @parsedConfig
END;
2. В версии 7.8 в таблице ContactDuplicateSearchResult были поля ContactId, GroupId, RuleId, GroupHash
А где-то с 7.8.3 добавилось ещё поле SysAdminUnitId
Но GroupHash не добавлялось и раньше, было так:
INSERT INTO [ContactDuplicateSearchResult] ([ContactId], [GroupId], [RuleId])
А теперь так:
INSERT INTO [ContactDuplicateSearchResult] ([ContactId], [GroupId], [RuleId], [SysAdminUnitId])

3. Что касается "Названия процедуры", то это поле действительно появилось с 7.8.3. Так что инструкция с академии подходит именно для версий 7.8.3+, т.к.

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

Сделал новую страницу в «Активностях» пропала логика поиска «Счета». Т.е. Если открыть справочник счета в стандартной «задаче» - отображает все счета которые выписаны на этого контрагента. Если же открыть справочник поля «счет» в новой странице активности — справочник вообще пустой.

Нравится

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

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

По умолчанию фильтрация счетов реализована бизнес-правилами в схеме ActivityPageV2. Если на новой странице счета не отображаются, тогда могут быть следующие варианты:
1) У пользователя нет прав (маловероятно)
2) При добавлении на страницу редактирования было добавлено новое поле "Счет" на основании нового объекта. В результате в новом объекте нет записей
3) Были настроены бизнес-правила для фильтрации записей, однако они были настроены некорректно.

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

П.С. счет не отображается если заполнено поля "Контрагент" и "Контакт" (если только "Контрагент" - все ок)

Что нужно поправить?

"Полищук Виталий Романович" написал:отображает все счета которые выписаны на этого контрагента

Точно? В пакете Invoice валяется ActivityPageV2:

"Invoice": {
	"FiltrationInvoiceByAccount": {
		"ruleType": BusinessRuleModule.enums.RuleType.FILTRATION,
		"autocomplete": true,
		"autoClean": true,
		"baseAttributePatch": "Account",
		"comparisonType": Terrasoft.ComparisonType.EQUAL,
		"type": BusinessRuleModule.enums.ValueType.ATTRIBUTE,
		"attribute": "Account"
	},
	"FiltrationInvoiceByContact": {
		"ruleType": BusinessRuleModule.enums.RuleType.FILTRATION,
		"autocomplete": true,
		"autoClean": true,
		"baseAttributePatch": "Contact",
		"comparisonType": Terrasoft.ComparisonType.EQUAL,
		"type": BusinessRuleModule.enums.ValueType.ATTRIBUTE,
		"attribute": "Contact"
	}
}

Это ж вроде как фильтрация и по контакту, и по контрагенту.

Здравствуйте,
Проблема связана с тем, что в счете, на данный момент поля «Контакт» и «Контрагент» нет возможности установить одновременно, только через мультилукап «Клиент», то есть в любом случае будет проставлен ИЛИ Контрагент, ИЛИ Контакт.
В Активностях же, если выбрать контакта, будет проставлен и контрагент, и фильтрация бизнес правилами: описанная тут: http://www.community.terrasoft.ua/forum/topic/24928#comment-66209
Будет работать через условное «И». То есть попытается найти счета, в которых И Контрагент, И Контакт равны тем что указаны в Активности. А таких нет, т.к. в счетах стоит или контакт, или контрагент.
Вам нужно отключить данную фильтрацию бизнес правилами, как это указано тут: http://www.community.terrasoft.ru/forum/topic/24861#comment-65997
После чего вам будут доступны все счета, в данной колонке, так же, для удобства можно написать фильтрацию с условным «ИЛИ», но не бизнес правилом, а через атрибут по примеру: http://www.community.terrasoft.ru/forum/topic/24859#comment-65965

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