Symptoms

Bug report:

Type: Terrasoft.SourceCodeException

Message: TypeError: null is not an object (evaluating 'lookupModel.PrimaryColumnName')

AdditionalInfo: Script: file:///var/containers/Bundle/Application/xxxxxx-xxxx-xxxxx-xxxxx-xxxxxxxx/BPMonlineMobile.app/www/appV2/Common/Terrasoft.Mobile.Combined.js%0D%0A%09Line: 12183 Stack trace:

Terrasoft.core#showUncaughtException@file:///var/containers/Bundle/Application/xxxxxx-xxxx-xxxxx-xxxxx-xxxxxxxx/BPMonlineMobile.app/www/appV2/Common/Terrasoft.Mobile.Combined.js:2821:38

Terrasoft.core#onWindowError@file:///var/containers/Bundle/Application/xxxxxx-xxxx-xxxxx-xxxxx-xxxxxxxx/BPMonlineMobile.app/www/appV2/Common/Terrasoft.Mobile.Combined.js:2463:39

Cause

1. In the mobile application wizard, the primary column is not displayed.

2. In the object (for example, "Account") there is no primary column for display.

Solution

To solve the problem, go to the [Mobile Application Wizard] and re-save the List Settings, Page Settings, and Detail Settings. Save all changes in the mobile app wizard.

Like 0

Like

Share

0 comments
Show all comments

Question

Kindly advise how I can put "Ukraine" at the top of the list in the [Countries] lookup (not a drop-down list).

Answer

Create a "Country" replacing object and add a UsrSort (Priority) integer column with the "0" default value therein.

Add and execute an SQL script in the configuration, which will arrange the priority as you need it - Ukraine will come first and all the rest of the countries will be arranged in the alphabetical order:

Script text:

UPDATE Country SET UsrSort = 0 WHERE Name = 'Ukraine'
 
DECLARE @sort INT
DECLARE @id uniqueidentifier
DECLARE @getid CURSOR
 
SET @sort = 1
SET @getid = CURSOR FOR
SELECT Country.Id FROM Country
WHERE Name Not In ('Ukraine')
ORDER BY Name
 
OPEN @getid
FETCH NEXT
FROM @getid INTO @id
WHILE @@FETCH_STATUS = 0
BEGIN
    UPDATE Country SET UsrSort = @sort WHERE Id = @id
    SET @sort = @sort + 1
    FETCH NEXT
    FROM @getid INTO @id
END
 
CLOSE @getid
DEALLOCATE @getid

You can later on display this column in the record list via the "View" - "Select fields to display" and use it for sotring via "View"- "Sort by".

Like 0

Like

Share

0 comments
Show all comments

Question

We are trying to optimize the synchronization time of the mobile application (offline), and one of the steps is image optimization.

How can we set the target image size (for example 1280 x 800)?

For example, there is a feature in Appache Cordova for this exact scenario.

Is it possible to do this in the settings or is it necessary to change the code?

Answer

We already optimaze images in the app.

Below is the code used in the base version:

Terrasoft.Camera.captureFromCamera({
            quality: 70,//в процентах
            size: 1280,//по максимальной стороне
            success: function() {},
            failure: function() {},
            scope: this
        });

This code enables you to change the image size:

Terrasoft.sdk.RecordPage.configureColumn("Opportunity", "opportunityFilesDetail", "Data", {
    quality: 50
});

 

Like 0

Like

Share

0 comments
Show all comments

Symptoms

We do not have employee birthdays displayed in the communication panel. I have set a bithday date for an employee and changed the notification period in the corresponding system setting today, however, no notifications are visible in the communication panel.

Cause

The [Current employment] detail is not populated.

Solution

The noteworthy event notifications can only be received if the [Current employment] detail is populated.

Like 0

Like

Share

0 comments
Show all comments

This article explains how to perform bulk data export/import between SQL Server databases.

This process should be performed in NOT business hours.

TABLE EXPORT

1. Create directories

C:\Export

C:\Export\Data\

C:\Export\Data\Error\

C:\Export\Data\Log\

2. In the script bellow specify the correct db name instead of /SourceDBName/ and source server name instead of /ServerName/. In this example bcp utility connects to SQL Server with a trusted connection using integrated security.

Export entire table:
bcp SourceDBName.dbo.SourceTableName OUT C:\Export\Data\SourceTableName.bcp -m 1 -n -e C:\Export\Data\Error\Error_out.log -o C:\Export\Data\Log\Output_out.log -S[ServerName] -T
 
Export data from select statement(data file + format file):
--Export data
bcp "SELECT Name FROM SourceDBName.dbo.SourceTableName" queryout SourceTableName.dat -c -T -S[ServerName]
--Export format file
bcp SourceDBName.dbo.SourceTableName format nul -x -f SourceTableName.xml -T -Sint-ms\mssql2016 -c

3. Run CMD as Administrator and execute the script from step 2

bcp will create the following 

SourceTableName.bcp data file (C:\Export\Data\SourceTableName.bcp)

Error_out.log (C:\Export\Data\Error\Error_out.log)

Output_out.log (C:\Export\Data\Log\Output_out.log)

Review Error_out.log and Output_out.log.

Error_out.log should be blank.

 

DATA IMPORT

1. Create temporary table

SELECT * INTO Data_IMPORT
FROM TargetTableName
WHERE 1 = 2;

2. Run cmd. with the following script and specify the correct db name insted of TargetDName and server name instead of ServerName

1. Import entire table with bcp IN

bcp TargetTable IN C:\Export\Data\SourceTableName.bcp -b 5000 -h "TABLOCK" -m 1 -n -e C:\Export\Data\Error\Error_in.log -o C:\Export\Data\Log\Output_in.log -S[ServerName] -T -q

2. Import data from data file with INSERT INTO ... FROM OPENROWSET(BULK

INSERT INTO dbo.TargetTable
SELECT *
FROM OPENROWSET(BULK 'D:\Data\SourceTableName.txt',
    FORMATFILE = 'D:\Data\SourceTableName.xml') as t1;

Wait until the operation is done. It can take up to few hours depending on the amount of data you are exporting.

You can look through Output_out.log to understand the export status.

3. Insert into destination table

CREATE NONCLUSTERED INDEX IX_SourceImportTableName_Id
    ON SourceImportTableName(Id);
GO
 
SET NOCOUNT ON;
DECLARE @BatchSize INT = 1000;
DECLARE @I INT = 0;
--Calculate number of iterations
DECLARE @TotalCount INT = (SELECT COUNT(*) / @BatchSize
    FROM SourceImportTableName imp WITH(NOLOCK)
    WHERE NOT EXISTS(
       SELECT Id
       FROM TargetTableName l WITH(NOLOCK)
       WHERE l.Id = imp.Id));
WHILE (@I < @TotalCount)
BEGIN
INSERT INTO Lead WITH(TABLOCK)
SELECT TOP(@BatchSize) *
FROM SourceImportTableName imp
WHERE NOT EXISTS(
    SELECT Id
    FROM TargetTableName l
    WHERE l.Id = imp.Id)
SET @I = @I + 1;
END;

Here are example scripts to import Lead table on server int-ms\mssql2016

--Export
bcp SourceDBName.dbo.Lead OUT C:\Export\Data\Lead.bcp -m 1 -n -e C:\Export\Data\Error\Error_out.log -o C:\Export\Data\Log\Output_out.log -Sint-ms\mssql2016 -T
 
--Import
bcp TargetDBName.dbo.Lead IN C:\Export\Data\Lead.bcp -b 5000 -h "TABLOCK" -m 1 -n -e C:\Export\Data\Error\Error_in.log -o C:\Export\Data\Log\Output_in.log -Sint-ms\mssql2016 -T -q
 
--Insert data into destination table
USE TargetDBName;
CREATE NONCLUSTERED INDEX IX_Lead_Id
    ON Lead_IMPORT(Id);
GO
 
SET NOCOUNT ON;
DECLARE @BatchSize INT = 1000;
DECLARE @I INT = 0;
--Calculate number of iterations
DECLARE @TotalCount INT = (SELECT COUNT(*) / @BatchSize
    FROM Lead_IMPORT imp WITH(NOLOCK)
    WHERE NOT EXISTS(
       SELECT Id
       FROM Lead l WITH(NOLOCK)
       WHERE l.Id = imp.Id));
WHILE (@I < @TotalCount)
BEGIN
INSERT INTO Lead WITH(TABLOCK)
SELECT TOP(@BatchSize) *
FROM Lead_IMPORT imp
WHERE NOT EXISTS(
    SELECT Id
    FROM Lead l
    WHERE l.Id = imp.Id)
SET @I = @I + 1;
END;

Example: Import part of the bcp data file

--Export
bcp Azull_D_1.dbo.Account OUT C:\Export\Data\Account.bcp -m 1 -n -e C:\Export\Data\Error\Error_out.log -o C:\Export\Data\Log\Output_out.log -Sint-ms\mssql2016 -T
--Format file
bcp Azull_D_1.dbo.Account format nul -x -f Account.xml -T -Sint-ms\mssql2016 -m 1 -n
--Load data
INSERT INTO dbo.Account
SELECT *
FROM OPENROWSET(BULK 'D:\Data\Account.bcp',
    FORMATFILE = 'D:\Data\Account.xml') as t1
WHERE Createdon > '2017-08-01 00:00:00';

Example: Export/Import some Accounts from select statement

bcp "SELECT * FROM Azull_D_1.dbo.Account WHERE ModifiedOn > '2017-08-01 00:00:00'" queryout Account.txt -T -Sint-ms\mssql2016 -c
bcp Azull_D_1.dbo.Account format nul -x -f Account.xml -T -Sint-ms\mssql2016 -c
 
INSERT INTO dbo.Account
SELECT *
FROM OPENROWSET(BULK 'D:\Data\Account.txt',
    FORMATFILE = 'D:\Data\Account.xml') as t1;

Here is a link to full bcp utility documentation https://docs.microsoft.com/en-us/sql/tools/bcp-utility.

https://docs.microsoft.com/en-us/sql/relational-databases/import-export/create-a-format-file-sql-server

Like 0

Like

Share

0 comments
Show all comments

Prerequisites

The section objects should be accessible for portal users.

Open access to custom objects in portal

 

1. On dev environment run script to create [int_RegisterSectionInPortal] stored procedure.

Note. Procedure uses string_split function which is available only under compatibility level 130 and above (see details here).

int_RegisterSectionInPortal stored procedure 

create or alter proc [int_RegisterSectionInPortal] (@EntityName NVARCHAR(MAX), @PortalId uniqueidentifier = 'C8565240-1DA3-4A68-BD4E-280F17B0D32E')
as
begin transaction;
set nocount on;
set transaction isolation level read uncommitted;
set xact_abort on;
begin try
if @EntityName = '' OR @EntityName IS NULL
throw 50001, 'Parameter @EntityName is empty', 1;
declare @PortalSysModuleEntity table (Id uniqueidentifier, BaseRecordId uniqueidentifier, TypeColumnUId uniqueidentifier, SysEntitySchemaUId uniqueidentifier);
declare @SchemaName table (Name nvarchar(250) NOT NULL);
declare @temp table (Id uniqueidentifier);
insert into @SchemaName
select value 
from string_split(@EntityName, ',')
where rtrim(value) <> '';
if (select COUNT(*) from @SchemaName) < 1
throw 50002, 'Parameter @EntityName has wrong format. It should contain entities comma separated names.', 1;
insert into @PortalSysModuleEntity (Id, BaseRecordId, TypeColumnUId, SysEntitySchemaUId)
select NEWID(), e.Id, TypeColumnUId, e.SysEntitySchemaUId
from SysModuleEntity e
where e.SysEntitySchemaUId in (
    select [uid]
    from SysSchema sh
        inner join @SchemaName n on n.Name = sh.Name
    where ExtendParent = 0
)
insert into SysModuleEntity(Id, TypeColumnUId, SysEntitySchemaUId, CreatedOn)
select Id, TypeColumnUId, SysEntitySchemaUId, GETUTCDATE()
from @PortalSysModuleEntity
select Id as SysModuleEntity
from @PortalSysModuleEntity;
insert into SysModule (
            [CreatedOn]
           ,[Caption]
           ,[SysModuleEntityId]
           ,[Image16]
           ,[Image20]
           ,[FolderModeId]
           ,[GlobalSearchAvailable]
           ,[HasAnalytics]
           ,[HasActions]
           ,[HasRecent]
           ,[Code]
           ,[HelpContextId]
           ,[ProcessListeners]
           ,[SysPageSchemaUId]
           ,[ModuleHeader]
           ,[Attribute]
           ,[CardSchemaUId]
           ,[SectionModuleSchemaUId]
           ,[SectionSchemaUId]
           ,[CardModuleUId]
           ,[TypeColumnValue]
           ,[Image32Id]
           ,[LogoId])
output inserted.Id into @temp
select      GETUTCDATE()
           ,s.[Caption] + ' Portal'
           ,p.Id
           ,s.[Image16]
           ,s.[Image20]
           ,s.[FolderModeId]
           ,s.[GlobalSearchAvailable]
           ,s.[HasAnalytics]
           ,s.[HasActions]
           ,s.[HasRecent]
           ,s.[Code]
           ,s.[HelpContextId]
           ,s.[ProcessListeners]
           ,s.[SysPageSchemaUId]
           ,s.[ModuleHeader]
           ,s.[Attribute]
           ,s.[CardSchemaUId]
           ,s.[SectionModuleSchemaUId]
           ,s.[SectionSchemaUId]
           ,s.[CardModuleUId]
           ,s.[TypeColumnValue]
           ,s.[Image32Id]
           ,s.[LogoId]
from SysModule
    inner join SysModuleEntity sme on sme.Id = SysModule.SysModuleEntityId
    inner join @PortalSysModuleEntity p on p.BaseRecordId = sme.Id
    inner join SysModule s on s.SysModuleEntityId = p.BaseRecordId
select Id as SysModule
from @temp;
delete from @temp;
insert into SysModuleEdit (ActionKindCaption, ActionKindName, CardSchemaUId, HelpContextId, MiniPageSchemaUId, PageCaption, SearchRowSchemaUId, SysModuleEntityId, SysPageSchemaUId, TypeColumnValue, UseModuleDetails, CreatedOn)
output inserted.Id into @temp
select e.ActionKindCaption, e.ActionKindName, e.CardSchemaUId, e.HelpContextId, e.MiniPageSchemaUId, e.PageCaption, e.SearchRowSchemaUId, p.Id, e.SysPageSchemaUId, e.TypeColumnValue, e.UseModuleDetails, GETUTCDATE() CreatedOn
from SysModuleEdit e
    inner join @PortalSysModuleEntity p on p.BaseRecordId = e.SysModuleEntityId
where e.SysModuleEntityId in (
select Id
from SysModuleEntity e
where e.SysEntitySchemaUId in (
    select [uid]
    from SysSchema sh
        inner join @SchemaName n on n.Name = sh.Name
    where ExtendParent = 0
))
select Id as SysModuleEdit
from @temp;
delete from @temp;
insert into SysModuleEntityInPortal(SysPortalId, SysModuleEntityId, CreatedOn)
output inserted.Id into @temp
select @PortalId, p.Id, GETUTCDATE()
from @PortalSysModuleEntity p
select Id as SysModuleEntityInPortal
from @temp;
delete from @temp;
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. On dev environment execute a stored procedure to register sections in the portal.

Stored procedure [int_RegisterSectionInPortal] takes as an argument comma separated list of section table names.

Example

exec dbo.[int_RegisterSectionInPortal] 'lcBwJob,lcBwLine,lcBwVeh,lcBwCc,lcBwDevice'

3. Add sections to the portal workplace (see figure 0)

4. Bind new data to a package with a filter by ids from output(see figure 1-2)  or by CreatedOn = Today (see figure 3) for the following system tables:

  • SysModuleEntity
  • SysModule
  • SysModuleEdit
  • SysModuleEntityInPortal

Figure 0. Add sections to portal workplace

Figure 1. Retrieve new records ids from the output

Figure 2. Bind data by ids from output

Figure 3. Bind data by date

Like 0

Like

Share

0 comments
Show all comments

Symptoms

Slow operation of the [Connected to] detail of the [Accounts] section (dashboard view)

Cause

Internal implementation of the diagram.js component and the display mechanism of detail elements (RelationshipDiagramViewModel).

Solution

In version 7.7.0, the diagram.js component implementation has been considerably improved. To transfer the functionality to version 7.6., download the module from the UsrDiagram.md file to the Custom  package, which will fully override the "Terrasoft.Diagram" base class. Add the replacing client module for the AccountRelationshipDetailV2 detail and add connection with the UsrDiagram module and overriding of some view model methods of the diagram.

Example of a code:

define("AccountRelationshipDetailV2", ["UsrDiagram"], function() {
		return {
			methods: {
				getMinLevel: function(accounts) {
					return accounts[0].level;
				},
 
				getMaxLevel: function(accounts) {
					return accounts[accounts.length - 1].level;
				},
 
				buildDiagramNodes: function(accounts) {
					this.clearAllDiagramNodes();
					var nodes = this.get("Nodes");
					var accountConfigs = {};
					accounts.forEach(function(account) {
						accountConfigs[account.id] = this.getNodeConfig(account);
					}, this);
					nodes.loadAll(accountConfigs);
					this.createNodeConnections(accounts);
				},
 
				createNodeConnections: function(accounts) {
					var nodes = this.get("Nodes");
					var connectionConfigs = {};
					var maxLevel = this.getMaxLevel(accounts);
					var filteredAccounts = accounts.filter(function(item) {
						return item.level < maxLevel;
					});
					filteredAccounts.forEach(function(account) {
						account.children.forEach(function(child) {
							connectionConfigs[account.id + "/" + child.id] = this.getConnectionConfig(child, account);
						}, this);
					}, this);
					nodes.loadAll(connectionConfigs);
				}
			},
 
			diff: /**SCHEMA_DIFF*/ []/**SCHEMA_DIFF*/
		};
	}
);

For versions 7.7.0-7.8.0, it will be enough to override the view model methods. In later versions, we plan to optimize this detail further.

Necessary conditions and possible restrictions

When updating from version 7.6.0 to 7.7.0 and higher, delete the UsrDiagram schema described above as well as its links. 

 

File attachments
Like 0

Like

Share

0 comments
Show all comments

Case

When the catalogue structure is changed, catalogues cannot be opened.

Solution

In the FolderManagerViewModel  schema of the ProductOmnichannel  package, make the following changes in the getCatalogueLevelItemsSelect()  method:

repace the strings:

select.addColumn("Id", "ColumnPathValueId");
var column = select.addColumn("Name", "ColumnPathValueName");

for the following:

select.addMacrosColumn(Terrasoft.QueryMacrosType.PRIMARY_COLUMN, "ColumnPathValueId");
var column = select.addMacrosColumn(Terrasoft.QueryMacrosType.PRIMARY_DISPLAY_COLUMN,  "ColumnPathValueName");

These changes are needed because a customer might not have the [Name] field in the object at all.

Necessary conditions:

Verison 7.6

Like 0

Like

Share

0 comments
Show all comments

Question

I want to perform ESQ from rootSchemaName: "X". How do I know which object property is its text view (the column value displayed in the screenshot)?

We receive responses to some requests that are not mine. In these responses, there are objects with the displayValue property, which is exactly what I need.

Example of a code:

var select = Ext.create("Terrasoft.EntitySchemaQuery", {
    rootSchemaName: dimensionItem.get("SysSchemaName")
});
 
select.getEntityCollection(function(response) {
    if (response.success) {
        var collection = response.collection;
        if (collection && collection.getCount() > 0) {
 
        }
    }
})

Answer

To receive the column values marked as Displayed name in an object via esq, use the esq.addMacrosColumn() esq method.

Example of a code:

var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
    rootSchemaName: 'UsrTestObj'
});
esq.addMacrosColumn(Terrasoft.QueryMacrosType.PRIMARY_DISPLAY_COLUMN, "displayValue");
esq.addMacrosColumn(Terrasoft.QueryMacrosType.PRIMARY_COLUMN, "value");
esq.getEntityCollection(function(result) {
    if (result.success) {
        debugger;
    }
}, this);

As a result, you receive the Id column value collection and the column marked as Displayed value from the UsrTestObj table.

Like 0

Like

Share

2 comments

Hi,



Is there a way to do this in C#?



Thank you.

Solem Khan Abdusalam,

For server-side C# ESQ, the entities returned by GetEntity and GetEntityCollection include a property for this:

var displayText = entity.PrimaryDisplayColumnValue;

Ryan

Show all comments

Symptoms

Bug report sample:

Terrasoft-Mobile":"true","Accept":"application/json","Content-Type":"application/json","Authorization":"Cookie"},"method":"GET","disableCaching":false},"performanceCounter":{"startDate":"2015-07-24T08:26:56.702Z"}},"headers":{"X-Terrasoft-Mobile":"true","Accept":"application/json","Content-Type":"application/json","Authorization":"Cookie"},"method":"GET","disableCaching":false},"async":true},"requestId":8,"status":500,"statusText":"Internal Server Error","responseText":"Terrasoft.Mobile.MobileModelLoopException: Models specified in the mobile application manifest have circular relationships\r\n   at Terrasoft.Mobile.MobileModelTopologicalSorter.Sort()\r\n   at Terrasoft.Mobile.MobileModelGraph.Build()\r\n   at Terrasoft.Mobile.MobileManifest.BuildModelGraph()\r\n   at Terrasoft.Mobile.MobileUtilities.GetAppMetadata(HttpContextBase context)\r\n   at Terrasoft.WebApp.Mobile.Services.MobileCodeService.ProcessRequest(HttpContext context)\r\nCycle: [Account,KnowledgeBase]","responseXML":null,"responseBytes":null} 

Calls sequence:

Solution

To solve, you must create (Add - Source code) a custom manifest (for example, MobileApplicationManifestCustom) and specify the "Javascript" language.

For version 7.6 and higher, if MobileApplicationManifest is not in Custom, you need to replace the parent manifest schema. To do this, in the mobile application wizard, select "Section settings" for the workplace and click the "Save" button.

If the custom manifest already exists, open it and add the following code:

{
    "Loops": [
        ["Account", "KnowledgeBase"],
    ]
}

where ["Account", "KnowledgeBase"] - links that must be specified.

The value is written from the value.

For example (from the bug report):

If

Cycle: [Invoice,Contract]","responseXML":null,"responseBytes":null}

Then

Specify the following code:

{
    "Loops": [
        ["Invoice”,”Contract "],                   
    ]
}

If the mobile app version is 7.5 and lower, you also need a manifest (for example, MobileApplicationManifestCustom) in the MobileApplicationManifest system setting:

And check the synchronization. If it ends with an error, then most likely it is still necessary to specify the connection in the custom manifest. As a result, add to the manifest until synchronization ends successfully.

Like 0

Like

Share

0 comments
Show all comments