Case description:

In agent desktop group queue item tabs by queue (see Figure 1).

 

Figure 1. Agent desktop

Algorithm of realization:

  1. Create replacing client schema of OperatorQueues (must be inherited from "Schema - Agent queues")
  2. Override loadQueues, queueTabChange and createQueuesTabs methods as following:

    define("OperatorQueues", ["terrasoft"],
        function (Terrasoft) {
            return {
                attributes: {},
                methods: {
                    loadQueues: function (callback) {
                        var esq = Ext.create("Terrasoft.EntitySchemaQuery", {
                            rootSchemaName: "Queue"
                        });
                        esq.isDistinct = true;
                        esq.addColumn("Id");
                        esq.addColumn("Name");
                        esq.addColumn("QueueEntitySchema");
                        esq.addColumn("[SysSchema:UId:QueueEntitySchema].Name", "EntitySchemaName");
                        esq.addColumn("[QueueObject:EntitySchemaUId:QueueEntitySchema].IsClosedQueue", "IsClosedQueue");
                        this.appendOperatorFilters(esq);
                        this.addQueueInProgressFilters(esq);
                        esq.getEntityCollection(function (result) {
                            if (!result.success) {
                                callback();
                            }
                            callback(result.collection);
                        });
                    },
                    queueTabChange: function (activeTab) {
                        var queueId = activeTab.get("Id");
                        var entitySchemaUId = activeTab.get("EntitySchemaUId");
                        var entitySchemaName = activeTab.get("EntitySchemaName");
                        var isClosedQueue = activeTab.get("IsClosedQueue");
                        var loadModuleCallback = function () {
                            this.sandbox.loadModule("QueueModule", {
                                renderTo: "operatorQueueEntityContainer",
                                parameters: {
                                    QueueId: queueId,
                                    EntitySchemaUId: entitySchemaUId,
                                    EntitySchemaName: entitySchemaName,
                                    IsClosedQueue: isClosedQueue
                                }
                            });
                        }.bind(this);
                        var profile = this.get("Profile");
                        if (profile.activeEntitySchemaUId !== entitySchemaUId) {
                            profile.activeEntitySchemaUId = entitySchemaUId;
                            this.saveProfileData(loadModuleCallback);
                        } else {
                            loadModuleCallback.call();
                        }
                    },
                    createQueuesTabs: function (collection) {
                        var activeQueueTabName = null;
                        if (!collection) {
                            return;
                        }
                        var profile = this.get("Profile");
                        var savedActiveEntitySchemaUId = profile.activeEntitySchemaUId;
                        var queues = this.get("Queues");
                        queues.clear();
                        collection.each(function (item) {
                            var queueId = item.get("Id");
                            var queueName = item.get("Name");
                            var queueEntitySchema = item.get("QueueEntitySchema");
                            var queueEntitySchemaName = item.get("EntitySchemaName");
                            var isClosedQueue = item.get("IsClosedQueue");
                            if (queueEntitySchema) {
                                var queueUId = queueEntitySchema.value;
                                var queueCaption = queueName;
                                var name = this.getQueueTabName(queueId);
                                queues.add(queueId, Ext.create("Terrasoft.BaseViewModel", {
                                    values: {
                                        Id: queueId,
                                        Caption: queueCaption,
                                        Name: name,
                                        EntitySchemaUId: queueUId,
                                        EntitySchemaName: queueEntitySchemaName,
                                        IsClosedQueue: isClosedQueue
                                    }
                                }));
                                if (queueId === savedActiveEntitySchemaUId) {
                                    activeQueueTabName = this.getQueueTabName(savedActiveEntitySchemaUId);
                                } else if (Ext.isEmpty(activeQueueTabName)) {
                                    activeQueueTabName = name;
                                }
                            }
                        }, this);
                        this.set("ActiveQueueTabName", activeQueueTabName);
                    }
                },
                diff: []
            };
        }
    );

     

Like 0

Like

Share

0 comments
Show all comments

Example override class SummaryModule

SummaryModuleV2.js

define("UsrSummaryModuleV2", ["SummaryModuleV2"],
    function() {
        Ext.define("Terrasoft.SummaryModuleOverrided", {
            override: "Terrasoft.SummaryModule",
 
           /*
            * @override
            */
            getESQ: function() {
                var esq = this.callParent(arguments);
                esq.queryKind = Terrasoft.QueryKind.LIMITED;
                return esq;
            }
        });
    }
);

On the page, which use base class you need to add dependency to overridden class:

BaseSectionV2

define("BaseSectionV2", ["UsrSummaryModuleV2"], function() {
    return {
        methods: {},
        details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
        diff: /**SCHEMA_DIFF*/[]/**SCHEMA_DIFF*/
    };
});

 

Like 0

Like

Share

0 comments
Show all comments

Question

How can I set a value for an active record from section module in edit mode (vertical list)?

Answer

If the column, for which the value must be set, is among the active string columns, you can try saving the active string:

var activeRow = this.getActiveRow();
activeRow.set("YourColumnName", columnValue);
activeRow.saveEntity();

To make this code work, make sure the activeRow.columns collection contains a column with the YourColumnName name and the Terrasoft.ViewModelColumnType.ENTITY_COLUMN type (this constant equals 0).

You can also implement updating the value via a request, as follows:

var updateQuery = this.Ext.create("Terrasoft.UpdateQuery", {
        rootSchemaName: "EntitySchemaName"
});
var filters = updateQuery.filters;
filters.addItem(this.Terrasoft.createColumnFilterWithParameter(
        this.Terrasoft.ComparisonType.EQUAL, "Id", currentRecordId));
updateQuery.setParameterValue("YourColumnName", columnValue);
updateQuery.execute(callbackFunction, this);

 

Like 1

Like

Share

0 comments
Show all comments

Question

In the [Contacts] section, I created a [Driver's documents] detail, the UsrSchema6Detail schema. I need to display it, if the selected job title is [Driver]. If the job title is different or not selected at all, the detail is hidden.

 I added a business rule to the contact schema, but it does not work.

rules: {
   "UsrSchema6Detail": {
      BindParametrVisibilePlaceByType: {
         // Rule type: BINDPARAMETER.
         ruleType: BusinessRuleModule.enums.RuleType.BINDPARAMETER,
         // Rule is regulated by the VISIBLE field value.
         property: BusinessRuleModule.enums.Property.VISIBLE,
         conditions: [{
            // Expression of the left part of the condition.
            leftExpression: {
               //The ATTRIBUTE expression type indicates, that
               // the view model attribute (column)acts as the expression.
               type: BusinessRuleModule.enums.ValueType.ATTRIBUTE,
               // Name of the view model column, whose value was compared in the expression.
               attribute: "Job"
            },
            // Compare operation type.
            comparisonType: Terrasoft.ComparisonType.EQUAL,
            // Expression of the right part of the condition.
            rightExpression: {
               type: BusinessRuleModule.enums.ValueType.CONSTANT,
               value: "703e34d6-4113-43b5-84dc-2e1f8635c6d4"
            }
         }]
      }
   }
}

If I apply this rule to the [Department] column, it works OK.

Answer

Using business rules is not a good solution for your business case.

Below is an example of code for hiding the [Communication options] detail on the edit page of an [Account]. Create the AccountPagev2 replacing module, the following code is added in the diff property:

{
    "operation": "merge",
    "name": "Communications",
    "values": {
        "visible" : {
            "bindTo": "communicationsVisibility"
        }
    }
}

Declare the method responsible for detail visibility in the methods property:

communicationsVisibility: function(){
    var type = this.get("Type");
    return !!type && type.displayValue === "Our company";
}

As a result, the detail will be visible only in case the type is specified as "Our company". You can hide any detail similarly.

Like 0

Like

Share

0 comments
Show all comments

Symptoms

Bug report:

Type: Terrasoft.SourceCodeException

Message: TypeError: undefined is not an object (evaluating 'ruleConfig.rule')

Cause

BusinesRuleManager in the edit card executes the rules at the same time, in parallel.

Solution

1. In Configuration, add a custom schema with the “Source code”  type, e.g., with the “UsrMobileUtilities” name;

2. Paste the following code in the schema:

Ext.define("Terrasoft.BusinessRulesManager.Override", {
    override: "Terrasoft.BusinessRulesManager",
    /** * @private */
    doExecuteRules: function(config) {
        this.executionConfig = config;
        this.allRulesAreValid = true;
        this.executeRulesForNextRecord();
    },
    executeRules: function(config) {
        if (this.rulesToExecute > this.rulesExecuted) {
            this.waitRulesInProgressId = setInterval(function() {
                if (this.rulesToExecute === this.rulesExecuted) {
                    clearInterval(this.waitRulesInProgressId);
                    this.doExecuteRules(config);
                }
            }.bind(this), 500);
        } else {
            this.doExecuteRules(config);
        }
    }
});

3. Save changes.

4. Connect this schema in the mobile application manifest (for example, “MobileApplicationManifestDefaultWorkplace”) in the “CustomSchemas” section:

"CustomSchemas": [
    "UsrMobileUtilities"
]

5. Save changes.

Alternative solution: fill out the City, Regions and Countries lookups (connected fields must also be populated).

Like 0

Like

Share

0 comments
Show all comments

Question

What are the features of the camera API in the mobile application? (v 5.4)

Answer

BPMonlineMobile 5.4 uses PhoneGap 2.8.

You can read about the camera features here: http://cordova.apache.org/docs/en/2.8.0/cordova_camera_camera.md.html#C…

Like 0

Like

Share

0 comments
Show all comments

Question

How can I get a link to a picture added in the Images module section?

Answer

To receive the link to an image added into a module:

1. Add a dependency for the Terrasoft  library into define

2. Receive the picture config:

var imageConfig = resources.localizableImages.ImageListSchemaItem1;

The image name will be different.

3. Convert the config into a link:

var link = Terrasoft.ImageUrlBuilder.getUrl(imageConfig);

 

Like 0

Like

Share

0 comments
Show all comments

Question

I cannot perform search by opportunities if I do not know what the case of the opportunity name is.

Answer

In the base version, the filters by text fields do not depend on the case. Try adding "%" in front of the value that you specify in the search field - the opportunity name might be slightly different from it.

Like 0

Like

Share

0 comments
Show all comments

Prerequisites

The object must have displayed value.

1. Run script in dev environment to create [glb_RegisterSection] stored procedure

glb_RegisterSection stored procedure

CREATE OR ALTER PROC [glb_RegisterSection] (
  @EntityName       NVARCHAR(100),
  @SectionCaption   NVARCHAR(100),
  @SectionPageName  NVARCHAR(100),
  @EditPageName     NVARCHAR(100)
)
AS BEGIN TRANSACTION;
   SET NOCOUNT ON;
   SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
   SET XACT_ABORT ON;
BEGIN TRY
IF @EntityName = ''
    THROW 50001, 'Parameter @EntityName is empty', 1;
IF @SectionCaption = ''
    THROW 50001, 'Parameter @SectionCaption is empty', 1;
DECLARE @SysModuleId        UNIQUEIDENTIFIER = NEWID();
DECLARE @SysModuleEditId    UNIQUEIDENTIFIER = NEWID();
DECLARE @SysModuleEntityId  UNIQUEIDENTIFIER = NEWID();
DECLARE @SysEntitySchemaUId UNIQUEIDENTIFIER;
DECLARE @SectionSchemaUId   UNIQUEIDENTIFIER;
DECLARE @CardSchemaUId      UNIQUEIDENTIFIER;
DECLARE @ActionKindName     NVARCHAR(250);
DECLARE @PageCaption        NVARCHAR(250);
SELECT TOP 1
    @SysEntitySchemaUId = UId,
    @ActionKindName = Caption
FROM SysSchema
WHERE Name = @EntityName
    AND ExtendParent = 0;
SELECT TOP 1
    @SectionSchemaUId = UId
FROM SysSchema
WHERE Name = @SectionPageName
    AND ExtendParent = 0;
SELECT TOP 1
    @CardSchemaUId = UId,
    @PageCaption = Caption
FROM SysSchema
WHERE Name = @EditPageName
    AND ExtendParent = 0;
IF @SysEntitySchemaUId IS NULL
    THROW 50002, 'Entity not found. Check @EntityName input parameter.', 1;
IF @SectionSchemaUId IS NULL
    THROW 50002, 'Section page not found. Check @SectionPageName input parameter.', 1;
IF @CardSchemaUId IS NULL
    THROW 50002, 'Edit page not found. Check @EditPageName input parameter.', 1;
INSERT INTO SysModuleEntity (
    Id,
    SysEntitySchemaUId)
VALUES (
    @SysModuleEntityId,
    @SysEntitySchemaUId
);
INSERT INTO SysModuleEdit (
    Id,
    SysModuleEntityId,
    CardSchemaUId,
    UseModuleDetails,
    ActionKindCaption,
    ActionKindName,
    PageCaption)
VALUES (
    @SysModuleEditId,
    @SysModuleEntityId,
    @CardSchemaUId,
    1,
    'New',
    @ActionKindName,
    @PageCaption
);
INSERT INTO SysModule (
    Id,
    Caption,
    Code,
    SectionSchemaUId,
    SysModuleEntityId,
    CardSchemaUId,
    FolderModeId,
    SectionModuleSchemaUId,
    CardModuleUId,
    Image32Id)
VALUES (
    @SysModuleId,
    @SectionCaption,
    @EntityName,
    @SectionSchemaUId,
    @SysModuleEntityId,
    @CardSchemaUId,
    'B659D704-3955-E011-981F-00155D043204',
    'DF58589E-26A6-44D1-B8D4-EDF1734D02B4',
    '4E1670DC-10DB-4217-929A-669F906E5D75',
    '026742D9-390C-4778-BC46-9FA85C42677A'
);
SELECT
    @SysModuleId AS SysModule,
    @SysModuleEntityId AS SysModuleEntity,
    @SysModuleEditId AS SysModuleEdit;
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER() AS ErrorNumber,
       ERROR_MESSAGE() AS ErrorMessage;
IF @@TRANCOUNT > 0
    ROLLBACK TRANSACTION;
END CATCH;
IF @@TRANCOUNT > 0
    ROLLBACK TRANSACTION;

2. Create section and edit pages (if not exist)

 

Create Section page (parent BaseSectionV2)

define("UsrEntitySectionV2", [], function() {
    return {
        entitySchemaName: "UsrEntity",
        messages: {},
        mixins: {},
        attributes: {},
        methods: {},
        diff: /**SCHEMA_DIFF*/[]/**SCHEMA_DIFF*/
    };
});

Create Edit page (parent BaseModulePageV2)

define("UsrEntityPageV2", [], function() {
    return {
        entitySchemaName: "UsrEntity",
        messages: {},
        mixins: {},
        attributes: {},
        methods: {},
        details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
        diff: /**SCHEMA_DIFF*/[]/**SCHEMA_DIFF*/
    };
});

 

3. Execute a stored procedure in dev environment to register section.

Stored procedure [glb_RegisterSection] takes such arguments: EntityName, SectionCaption, SectionPageName, EditPageName.

Example

exec dbo.[glb_RegisterSection] 'UsrEntity', 'My entities', 'UsrEntitySectionV2', 'UsrEntityPageV2'



4. Bind new data to a package with a filter by IDs from output for the following system tables:

  • SysModuleEntity
  • SysModule
  • SysModuleEdit

Standard list of objects

EntityName, EntityName + "Folder", EntityName + "File", EntityName + "InFolder", EntityName + "Tag", EntityName + "InTag"

Like 0

Like

Share

9 comments

Can I use this approach to create new section for the "Relationship" object or "ContactCareer" object of BPM that came out of the box? If so, are there any extra steps I need to take?

 

kumar,

You can use this instruction to create a new section for the object.

Some details: 

When you create edit page and section page you should choose that options instead of module http://prntscr.com/mb5d9o



Also, it`s necessary to create a backup of the database before adding the section because it`s pretty difficult operation that can cause issues.



Please note, that created section and edit page should not contain the prefix because objects that you specified are system ones. You can simply temporarily remove it from the system setting "Prefix for object name".



And also it necessary to clear redis, relogin and compile the system after section was added.



Best regards,

Alex

Alex_Tim,

Do you know if it is possible to also add section folders when using this method? I've used the above to cover an object created as a detail to a full section, but not sure how to add & relate the EntityFolder and EntityInFolder objects so I can create folders in the section. Is this possible?

Thanks,

Ryan

For anyone else that comes across this, to add folders, all you need to do is add a new object named EntityName + "Folder" that inherits from BaseFolder as well as Entity + "InFolder" that inherits from BaseItemInFolder (and also add a lookup property to your custom entity as well as change the lookup for the virtual Folder property of the inherited properties). The code above already specifies the correct FolderModeId so once you add the object, log out and back in again, then you'll have folders for the entity.

Hello,

There is a failed case in this script. When an object has already been added in a Detail, it will duplicate SysModuleEntity, and the new edit page won't be used. System always uses the first page created. Therefore the detail edit page and the section edit page will always be the same. I updated the script a little bit to check if the SysModuleEntity and SysModuleEdit are created. 

 

CREATE OR ALTER PROC [glb_RegisterSection] (
	@EntityName       NVARCHAR(100),
	@SectionCaption   NVARCHAR(100),
	@SectionPageName  NVARCHAR(100),
	@EditPageName     NVARCHAR(100)
)
AS BEGIN TRANSACTION;
	SET NOCOUNT ON;
	SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
	SET XACT_ABORT ON;
BEGIN TRY
IF @EntityName = ''
	THROW 50001, 'Parameter @EntityName is empty', 1;
IF @SectionCaption = ''
	THROW 50001, 'Parameter @SectionCaption is empty', 1;
DECLARE @SysModuleId        UNIQUEIDENTIFIER = NEWID();
DECLARE @SysModuleEditId    UNIQUEIDENTIFIER;
DECLARE @SysModuleEntityId  UNIQUEIDENTIFIER;
DECLARE @SysEntitySchemaUId UNIQUEIDENTIFIER;
DECLARE @SectionSchemaUId   UNIQUEIDENTIFIER;
DECLARE @CardSchemaUId      UNIQUEIDENTIFIER;
DECLARE @ActionKindName     NVARCHAR(250);
DECLARE @PageCaption        NVARCHAR(250);
SELECT TOP 1
	@SysEntitySchemaUId = UId,
	@ActionKindName = Caption
FROM SysSchema
WHERE Name = @EntityName
	AND ExtendParent = 0;
SELECT TOP 1
	@SectionSchemaUId = UId
FROM SysSchema
WHERE Name = @SectionPageName
	AND ExtendParent = 0;
SELECT TOP 1
	@CardSchemaUId = UId,
	@PageCaption = Caption
FROM SysSchema
WHERE Name = @EditPageName
	AND ExtendParent = 0;
IF @SysEntitySchemaUId IS NULL
	THROW 50002, 'Entity not found. Check @EntityName input parameter.', 1;
IF @SectionSchemaUId IS NULL
	THROW 50002, 'Section page not found. Check @SectionPageName input parameter.', 1;
IF @CardSchemaUId IS NULL
	THROW 50002, 'Edit page not found. Check @EditPageName input parameter.', 1;
 
Select TOP 1
	@SysModuleEntityId = Id
From SysModuleEntity
Where SysEntitySchemaUId = @SysEntitySchemaUId
 
if (@SysModuleEntityId IS NULL)
BEGIN
	SELECT @SysModuleEntityId = NEWID()
	INSERT INTO SysModuleEntity (
		Id,
		SysEntitySchemaUId)
	VALUES (
		@SysModuleEntityId,
		@SysEntitySchemaUId
	);
END
 
Select TOP 1
	@SysModuleEditId = Id
From SysModuleEdit
Where SysModuleEntityId = @SysModuleEntityId
 
IF @SysModuleEditId IS NULL
BEGIN
	SELECT @SysModuleEditId = NEWID()
	INSERT INTO SysModuleEdit (
		Id,
		SysModuleEntityId,
		CardSchemaUId,
		UseModuleDetails,
		ActionKindCaption,
		ActionKindName,
		PageCaption)
	VALUES (
		@SysModuleEditId,
		@SysModuleEntityId,
		@CardSchemaUId,
		1,
		'New',
		@ActionKindName,
		@PageCaption
	);
END
INSERT INTO SysModule (
	Id,
	Caption,
	Code,
	SectionSchemaUId,
	SysModuleEntityId,
	CardSchemaUId,
	FolderModeId,
	SectionModuleSchemaUId,
	CardModuleUId,
	Image32Id)
VALUES (
	@SysModuleId,
	@SectionCaption,
	@EntityName,
	@SectionSchemaUId,
	@SysModuleEntityId,
	@CardSchemaUId,
	-- 'B659D704-3955-E011-981F-00155D043204', -- Use multiple folder
	'A24A734D-3955-E011-981F-00155D043204', -- Do not use folder
	'DF58589E-26A6-44D1-B8D4-EDF1734D02B4',
	'4E1670DC-10DB-4217-929A-669F906E5D75',
	'026742D9-390C-4778-BC46-9FA85C42677A'
);
SELECT
	@SysModuleId AS SysModule,
	@SysModuleEntityId AS SysModuleEntity,
	@SysModuleEditId AS SysModuleEdit;
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER() AS ErrorNumber,
		ERROR_MESSAGE() AS ErrorMessage;
IF @@TRANCOUNT > 0
	ROLLBACK TRANSACTION;
END CATCH;
IF @@TRANCOUNT > 0
	ROLLBACK TRANSACTION;



 

Hi, 

I followed the above steps . But there was no section created in any any of the workspace. Kindly suggest how to create new menu /section for the existing object.

Sriraksha KS,

Firstly, we highly do not recommend to create several sections per one object. Please note, that data will be duplicated in both sections, since they are referring to one object. You can create a new object in the system with the same range of columns and copy data from initial object to newly created. 

Nevertheless, if you intend to add section manually, please take a look at following tables: 

SysModule,

SysModuleEdit,

SysModuleEntity, 

SysModuleInWorkplace, 

SysSchema

 

Regards,

Anastasia

Does this still work for Freedom UI? Or is a new process required for achieving the same result now?

Harvey Adcock,

 

No, for Freedom UI sections, use the Freedom UI designer, which allows creation of sections for existing objects.

Show all comments

Case

A customer cannot log in to bpm'online (The element with ""  identifier not found)

Solution

First of all, try clearing Redis, compiling the application and updating the website page.

If the indicated actions do not help, execute the "Configuration check" and determine what section contains the error.

Republish the objects of the detected section (sections) and recompile.

Like 0

Like

Share

0 comments
Show all comments