Фильтры

Уже сегодня low-code технологии ускоряют внедрение ИТ-решений, а также снижают затраты компаний на цифровизацию. Чтобы изучить состояние и ключевые тенденции рынка low-code и узнать о перспективах его развития, мы запускаем масштабное глобальное исследование, в котором приглашаем принять участие бизнес- и ИТ-лидеров.

Результаты опроса лягут в основу ежегодного отчета о состоянии и перспективах рынка low-code, который поможет компаниям по всему миру построить конкурентную стратегию цифровой трансформации на 2021 и далее.

Присоединяйтесь, участие в опросе займет не более 10 минут!

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

РЫНОК LOW-CODE: СОСТОЯНИЕ И ПЕРСПЕКТИВЫ. ПРОЙТИ ОПРОС >> 

Нравится

Поделиться

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

Добрый день! 

При работе с правами на объекты в бизнес процессе, возникла ситуация когда стало необходимо вернуть права на запись (Entity), согласно настройкам на странице "Права доступа на объекты" раздела, например Лид.  Для этого можно воспользоваться классом DBSecurityEngine, например так:

EntitySchema schema = UserConnection.EntitySchemaManager.FindInstanceByName("Lead");
UserConnection.DBSecurityEngine.AddDefRights(new Guid("Ваш уникальный идентификатор записи"), schema);

Но выяснилось что метод AddDefRights класса DBSecurityEngine дублирует уже имеющиеся записи в таблице прав SysLeadRight. 

Переопределив данный класс можно избежать этого поведения, например:

using System;
using Terrasoft.Core;
using Terrasoft.Core.Configuration;
using Terrasoft.Core.DB;
using Terrasoft.Core.Entities;

namespace Terrasoft.Core.DB
{
    class UsrDBSecurityEngine : DBSecurityEngine
    {
        public UsrDBSecurityEngine() : base()
        {
        }
        
		new
        public void AddDefRights(Guid primaryColumnValue, EntitySchema schema)
        {
            AddDefRights(primaryColumnValue, UserConnection.CurrentUser.Id, UserConnection.CurrentUser.ContactId, schema);
        }

		new
        public void AddDefRights(Guid primaryColumnValue, Guid userId, Guid contactId, EntitySchema schema)
        {
            if (!Guid.Empty.Equals(userId))
            {
                InsertSelect recordDefRightsInsert = GetRecordDefRightsInsert(userId, contactId, schema.UId, Guid.Empty, Guid.Empty, isNewRecord: false);
                if (recordDefRightsInsert != null)
                {
                    recordDefRightsInsert.Parameters.GetByName("RecordId").Value = primaryColumnValue;
                    recordDefRightsInsert.Execute();
                }
            }
        }
        protected override QueryCondition GetRecordsByRightConditionUseDenyRecordRights(RecordsByRightOptions options)
        {
            throw new NotImplementedException();
        }
        internal virtual InsertSelect GetRecordDefRightsInsert(Guid userId, Guid contactId, Guid schemaUId, Guid recordId, Guid ownerId, bool isNewRecord)
        {
            string text = FindEntitySchemaNameByUId(schemaUId);
            if (string.IsNullOrEmpty(text))
            {
                return null;
            }
            if (!GetIsEntitySchemaAdministratedByRecordsInternal(text))
            {
                return null;
            }
            if (GetSchemaUseOwnRecordRights(text))
            {
                QueryParameter userIdParameter = new QueryParameter("UserId", userId);
                QueryParameter schemaUIdParameter = new QueryParameter("SchemaUId", schemaUId);
                QueryParameter queryParameter = new QueryParameter("RecordId", recordId);
                QueryParameter queryParameter2 = new QueryParameter("ContactId", contactId);
                Query recordDefRightsSelect = GetRecordDefRightsSelect(userId, schemaUIdParameter);
                if (isNewRecord)
                {
                    recordDefRightsSelect.Union(GetRecordDefRightsSelectByOperation(userIdParameter, EntitySchemaRecordRightOperation.Read)).Union(GetRecordDefRightsSelectByOperation(userIdParameter, EntitySchemaRecordRightOperation.Edit)).Union(GetRecordDefRightsSelectByOperation(userIdParameter, EntitySchemaRecordRightOperation.Delete));
                }
/*Запрос который решает проблему дублирования записей в таблице прав*/
                Select notExists = new Select(UserConnection)
                    .Column(Column.Parameter(1))
                    .From("Sys"+ text+ "Right").As("str")
                    .Where("str", "RecordId").IsEqual(queryParameter)
                    .And("str", "SysAdminUnitId").IsEqual("DefRightsSelect", "GranteeSysAdminUnitId")
                    .And("str", "Operation").IsEqual("DefRightsSelect", "Operation") as Select;
                Query subSelectQuery = new Select(UserConnection).Column(queryParameter).As("RecordId").Column("GranteeSysAdminUnitId")
                    .As("GranteeSysAdminUnitId")
                    .Column("Operation")
                    .As("Operation")
                    .Column("RightLevel")
                    .As("RightLevel")
                    .Column("Position")
                    .As("Position")
                    .Column("SourceId")
                    .As("SourceId")
                    .Column(queryParameter2)
                    .Column(queryParameter2)
                    .From(recordDefRightsSelect)
                    .As("DefRightsSelect").Where("").Not().Exists(notExists); /*добавляем сюда проверку нашим запросом*/
                InsertSelect insertSelect = new InsertSelect(UserConnection).Into(GetRecordRightsSchemaName(text))
                    .Set("RecordId", "SysAdminUnitId", "Operation", "RightLevel", "Position", "SourceId", "CreatedById", "ModifiedById")
                    .FromSelect(subSelectQuery);
                insertSelect.InitializeParameters();
                return insertSelect;
            }
            return null;
        }

        internal virtual Select GetRecordDefRightsSelect(Guid userId, QueryParameter schemaUIdParameter)
        {
            return new Select(UserConnection).Column("GranteeSysAdminUnitId").Column("Operation").Column("RightLevel")
                .Column("Position")
                .Column(Column.Parameter(RecordRightSource.Def))
                .As("SourceId")
                .Column(Column.Parameter(1))
                .As("Priority")
                .From("SysEntitySchemaRecordDefRight")
                .Where("SubjectSchemaUId")
                .IsEqual(schemaUIdParameter)
                .And()
                .Exists(new Select(UserConnection).Column(Column.Const(1)).From("SysAdminUnitInRole").Where("SysAdminUnitInRole", "SysAdminUnitId")
                    .IsEqual(Column.Parameter(userId))
                    .And("SysAdminUnitInRole", "SysAdminUnitRoleId")
                    .IsEqual("SysEntitySchemaRecordDefRight", "AuthorSysAdminUnitId") as Select)
                .And("Position")
                .IsEqual(new Select(UserConnection).Column(Func.Min("MinRightPosition", "Position")).From("SysEntitySchemaRecordDefRight").As("MinRightPosition")
                    .Where("MinRightPosition", "SubjectSchemaUId")
                    .IsEqual(schemaUIdParameter)
                    .And()
                    .Exists(new Select(UserConnection).Column(Column.Const(1)).From("SysAdminUnitInRole").Where("SysAdminUnitInRole", "SysAdminUnitId")
                        .IsEqual(Column.Parameter(userId))
                        .And("SysAdminUnitInRole", "SysAdminUnitRoleId")
                        .IsEqual("MinRightPosition", "AuthorSysAdminUnitId") as Select)
                    .And("MinRightPosition", "GranteeSysAdminUnitId")
                    .IsEqual("SysEntitySchemaRecordDefRight", "GranteeSysAdminUnitId")
                    .And("MinRightPosition", "Operation")
                    .IsEqual("SysEntitySchemaRecordDefRight", "Operation")) as Select;
        }

        internal Select GetRecordDefRightsSelectByOperation(QueryParameter userIdParameter, EntitySchemaRecordRightOperation operation)
        {
            return new Select(UserConnection).Column(userIdParameter).As("GranteeSysAdminUnitId").Column(Column.Parameter((int)operation))
                .Column(Column.Parameter(2))
                .Column(Column.Parameter(0))
                .As("Position")
                .Column(Column.Parameter(RecordRightSource.Author))
                .As("SourceId")
                .Column(Column.Parameter(0))
                .As("Priority")
                .From("SysOneRecord")
                .As("CreatorDefRightsSelect");
        }
    }
}

Далее можно вызвать наш переопределенный метод так:

EntitySchema schema = UserConnection.EntitySchemaManager.FindInstanceByName("Lead");
UsrDBSecurityEngine usrDBSecurityEngine = new UsrDBSecurityEngine();
usrDBSecurityEngine.Initialize(UserConnection);
usrDBSecurityEngine.AddDefRights(new Guid("Ваш уникальный идентификатор записи"), schema);

Надеюсь кому-то поможет. 

Нравится

Поделиться

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

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

Принятые допущения для инструмента миграции

Новый дизайнер взаимосвязей меняет способ представления данных о взаимосвязях. Ранее, деталь позволяла определить тип взаимосвязи между неким контрагентом/контактом А и контрагентом/контактом Б. Теперь же, для каждого из типов взаимосвязи установлена категория: формальная или неформальная связь. Формальная связь означает определенную иерархию (подчинение, например, работодатель-сотрудник, руководитель-подчиненный), а неформальная связь - просто взаимосвязь между сущностями (друзья, партнеры и тому подобное).

Также связи могут иметь позицию:

  • прямая — для добавления сущности, подчиненной текущей; 
  • обратная  — для добавления сущности, родительской для текущей;
  • горизонтальная — для добавления сущности, равной по иерархии текущей.

Такое разграничение типов взаимосвязи несет за собой ограничения при построении диаграммы с использованием нового дизайнера:

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

  • нет возможности создать цикл по формальным связям (то есть диаграмму вида контрагент 1 -> контрагент 2 -> контрагент 3 -> контрагент 1);

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

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

Алгоритм работы инструмента миграции

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

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

Выключение нового дизайнера взаимосвязей

В случае, если вы решили на первых порах не пользоваться новым дизайнером взаимосвязей, а использовать старую деталь, необходимо отключить функциональность (feature) UseRelationshipDesigner. В этом случае на карточке контрагента/контакта будет отображаться деталь [Взаимосвязи] вместо нового дизайнера. Данные, которые присутствовали на детали до миграции удалены не будут и при выключении дизайнера отобразятся. Данные, добавленные в новом дизайнере, в старую деталь не переносятся.

Запуск инструмента миграции вручную

Если вы отключили новый дизайнер, но хотите включить его позже, то миграция автоматически не выполнится — этот шаг присутствует только в сценарии обновления на версию 7.17.1. В этом случае, необходимо запустить миграцию вручную. Для этого в разделе “Управление конфигурацией” нужно найти и запустить процесс “Migrating data to the relationship designer”. После завершения процесса новый дизайнер будет готов к использованию с уже настроенными ранее в предыдущем механизме взаимосвязями. Перед началом миграции, процесс удалит все данные по взаимосвязям в новом дизайнере.

Нравится

Поделиться

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

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

Александр Нигматулин,

Доброго дня!

А вроде и раньше так было. Это как мы понимаем, на детали "Карьера" у контакта может быть только одно текущее место работы.

Сошина Дарья Алексеевна,

Я имею в виду, можно ли будет указывать взаимосвязь Сотрудник и Бывший сотрудник

Обновились до 7.17.1. Данные взаимосвязей не мигрировали автоматически. Процесса  “Migrating data to the relationship designer” в разделе "Библиотека процессов" Нет! Техподдержка ответила:

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

Алексей Следь, 

добрый день!

Пост на community отредактироавали. Спасибо!

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

Be Tech разработали уникальный коннектор к сервису “Нова Пошта”, который позволит вам еще быстрее создавать накладные и отправлять посылки получателю, не выходя из карточки Продажи или Заказа системы Creatio. 

 

Система Creatio интегрируется с Личным кабинетом и Бизнес кабинетом  компании в сервисе “Нова Пошта” и вы всегда будете владеть актуальным статусом ваших посылок. 

 

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

 

Возможности коннектора:

  • в системе Creatio отдельно настраивается раздел Новая почта, в котором вы можете контролировать и отслеживать все посылки, которые отправлены сервисом “Нова Пошта”;
  • в карточке каждого Контрагента есть возможность быстро добавлять/удалять/менять адрес доставки товара и выбирать удобные отделения для клиента;
  • менеджер всегда работает в едином окне и создает экспресс накладные прямо из карточки “Продажа” или “Заказ”, запустив бизнес процесс нажатием одной кнопки;
  • обновление статуса доставки происходит каждые 3 часа;
  • на вкладке “История”, всегда можно посмотреть какие доставки и когда осуществлялись вашему клиенту.

Чтобы узнать больше напишите студии Be Tech - welcome@btbpm.com 

Или закажите решение на Terrasoft Marketplace  

Нравится

Поделиться

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

При работе с правами в коде, когда настраиваешь их в бизнес процессе, по началу у меня часто возникал вопрос, что значат значения в колонке Operation и RightLevel таблиц прав на объекты такие как SysEntitySchemaRecordDefRight, SysLeadRight, SysContactRight и т.д. Значения для Operation в C# хранятся в перечислении:

Terrasoft.Core.Configuration.EntitySchemaRecordRightOperation

для RightLevel в: 

Terrasoft.Core.Configuration.EntitySchemaRecordRightLevel

 

В JavaScript их можно найти обратившись к переменной 

Terrasoft.RightsEnums

В ней хранятся как значения для Operation, так и для RightLevel.

Для удобства вот их значения.

Operation = 0 = чтение

Operation = 1 = запись

Operation = 2 = удаление

RightLevel = Deny = 0 - "Запрещено",
RightLevel = Allow = 1 - "Разрешено",
RightLevel = AllowAndGrant = 2 - "Разрешено с правом делегирования"

Нравится

Поделиться

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