SDK
support
cases

Add code below into methods section and bind openInputBox method.

Example: lookup fields to Contact and Account tables.

Pre-condition: add localizableStrings to your schema (UsrContactCaption, UsrAccountCaption, UsrInputBoxCaption).

openInputBox: function() {
    this.set("UsrContactCollection", new Terrasoft.Collection());
    this.set("UsrAccountCollection", new Terrasoft.Collection());
    this.set("UsrContact", null);
    this.set("UsrAccount", null);
    var controls = {
        "UsrContact": {
            dataValueType: Terrasoft.DataValueType.ENUM,
            isRequired: true,
            caption: resources.localizableStrings.UsrContactCaption,
            value: {
                bindTo: "UsrContact"
            },
            customConfig: {
                tag: "Contact",
                list: {
                    bindTo: "UsrContactCollection"
                },
                prepareList: {
                    bindTo: "getCollectionValues"
                },
                loadNextPage: {
                    bindTo: "loadCollectionNextPage"
                }
            }
        },
        "UsrAccount": {
            dataValueType: Terrasoft.DataValueType.ENUM,
            isRequired: true,
            caption: resources.localizableStrings.UsrAccountCaption,
            value: {
                bindTo: "UsrAccount"
            },
            customConfig: {
                tag: "Account",
                list: {
                    bindTo: "UsrAccountCollection"
                },
                prepareList: {
                    bindTo: "getCollectionValues"
                },
                loadNextPage: {
                    bindTo: "loadCollectionNextPage"
                }
            }
        }
    };
    Terrasoft.utils.inputBox(resources.localizableStrings.UsrInputBoxCaption,
        this.openInputBoxHandler,
        [Terrasoft.MessageBoxButtons.OK, Terrasoft.MessageBoxButtons.CANCEL],
        this,
        controls
    );
    Terrasoft.each(Terrasoft.MessageBox.controlArray, function(item) {
        item.control.bind(this);
    }, this);
},
getCollectionValues: function(filter, list, tag) {
    if (Ext.isEmpty(list)) {
        return;
    }
    list.clear();
    var esq = Ext.create("Terrasoft.EntitySchemaQuery", {
        rootSchemaName: tag,
        isPageable: true,
        rowCount: 20
    });
    this.buildCollectionQuery(esq, list, filter, tag);
},
loadCollectionNextPage: function(listParams, tag) {
    if (!this.get("CanLoadMore" + tag)) {
        return;
    }
    var esq = Ext.create("Terrasoft.EntitySchemaQuery", {
        rootSchemaName: tag,
        isPageable: true,
        rowCount: 20,
        rowsOffset: listParams.listView.collectionItemsCount
    });
    this.buildCollectionQuery(esq, listParams.list, listParams.filterValue, tag);
},
buildCollectionQuery: function(esq, list, filter, tag) {
    esq.addMacrosColumn(Terrasoft.QueryMacrosType.PRIMARY_COLUMN, "value");
    var orderColumn = esq.addMacrosColumn(Terrasoft.QueryMacrosType.PRIMARY_DISPLAY_COLUMN, "displayValue");
    orderColumn.orderDirection = Terrasoft.OrderDirection.ASC;
    esq.filters.addItem(esq.createPrimaryDisplayColumnFilterWithParameter(
        Terrasoft.ComparisonType.START_WITH, filter, Terrasoft.DataValueType.TEXT));
    esq.getEntityCollection(function(response) {
        if (response && response.success) {
            var preObject = {};
            response.collection.each(function(item) {
                preObject[item.get("value")] = item.values;
            }, this);
            list.loadAll(preObject);
            this.set("CanLoadMore" + tag, response.collection.getCount() === 20);
        }
    }, this);
},
openInputBoxHandler: function(returnCode, controlData) {
    if (Terrasoft.MessageBoxButtons.OK.returnCode === returnCode) {
        // TODO: your code here
    }
}

 

Like 0

Like

Share

2 comments

Hi 

I am using [Country ] and [City] lookup in the input box, But I have to apply the filter on these lookup. 



How is it possible to apply filter on lookups fields in input box ?



Many Thanks.

Dear Akshit,

 

In order to apply filtration over a lookup field in the InputBox please add the following code to the “buildCollectionQuery” method:



            buildCollectionQuery: function(esq, list, filter, tag) {

               esq.addMacrosColumn(Terrasoft.QueryMacrosType.PRIMARY_COLUMN, "value");

               var orderColumn = esq.addMacrosColumn(Terrasoft.QueryMacrosType.PRIMARY_DISPLAY_COLUMN, "displayValue");

               orderColumn.orderDirection = Terrasoft.OrderDirection.ASC;

               esq.filters.addItem(esq.createPrimaryDisplayColumnFilterWithParameter(

                   Terrasoft.ComparisonType.START_WITH, filter, Terrasoft.DataValueType.TEXT));

               esq.filters.addItem(esq.createColumnInFilterWithParameters("Name",

               ["Australia", "United States"]));


               esq.getEntityCollection(function(response) {

                   if (response.success) {

                       var preObject = {};

                       response.collection.each(function(item) {

                           preObject[item.get("value")] = item.values;

                       }, this);

                       list.loadAll(preObject);

                       this.set("CanLoadMore" + tag, response.collection.getCount() === 20);

                   }

               }, this);

            },



Please see the screenshot with the result https://prnt.sc/rtvqvm 



Additionally, please find more information about filtration in esq in the article by the link below:



https://academy.creatio.com/documents/technic-sdk/7-15/entityschemaquery-class-filters-handling

 

Best regards,

Norton

Show all comments

Case description

We want to show Printables (“PRINT” button with printables) for Portal user.

It looks like this:

In a page:

Algorithm of realization.

  1. Give portal user read access permissions to the objects:

1)      Printable (SysModuleReport)

2)      Tables of printable (SysModuleReportTable)

3)      Printable form type (SysModuleReportType)

4)      Section object (SysModuleEntity)

 

How to give read access permissions?

1)      In object you should set ON access by operations and publish object:

 

2) On “Objects permissions” tab in configuration add roles “All portal users” and “All employees” for this object and manage access level for them:

 

        2. In Lookups section find lookup “List of objects available for portal users” and add your objects:

The same operations you should to do for objects from step 1 (SysModuleReport, SysModuleReportTable, SysModuleReportType, SysModuleEntity).

After that clear redis and clear cache in the section and page where should show printables:

Like 0

Like

Share

2 comments

This was working for us till version 7.12.2.1728



Support states: "For now, printables are not yet compatible with the Creatio portal. Yes, they could be added to the portal but we cannot guarantee that they will work as expected."



So hoping it can be resolved soon.

in the latest version too we are unable to view the print option for the portal user though the object permission has been provided for SysModuleReport, SysModuleReportTable, SysModuleReportType, SysModuleEntity. any update from creatio?

 

Show all comments
knowledge base
SDK
Q&A
support

Question

How can I hide the [Add] buttons for some section types?

Answer

Create the section replacing schema:

define("DocumentSectionV2", ["VisaHelper", "ConfigurationConstants", "BaseFiltersGenerateModule"],
    function(VisaHelper, ConfigurationConstants, BaseFiltersGenerateModule) {
        return {
            entitySchemaName: "Document",
            methods: {
                initEditPages: function() {
                    var enabledEditPages = new this.Terrasoft.Collection();
                    this.callParent(arguments);
                    var editPages = this.get("EditPages");
                    var items = editPages.getItems();
                    for (var i = 0; i < items.length; i++) {
                        if (items[i].values.Id !== "2015b538-40d0-4cbf-9301-fa8cae37ae94") {
                            enabledEditPages.add(items[i]);
                        }
                    }
                    this.set("EnabledEditPages", enabledEditPages);
                }
            },
            diff: /**SCHEMA_DIFF*/[
                {
                    "operation": "merge",
                    "name": "SeparateModeAddRecordButton",
                    "parentName": "SeparateModeActionButtonsLeftContainer",
                    "propertyName": "items",
                    "values": {
                        "controlConfig": {
                            "menu": {
                                "items": {
                                    "bindTo": "EnabledEditPages",
                                    "bindConfig": {
                                        "converter": function(editPages) {
                                            if (editPages.getCount() > 1) {
                                                return editPages;
                                            } else {
                                                return null;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                {
                    "operation": "merge",
                    "name": "CombinedModeAddRecordButton",
                    "parentName": "CombinedModeActionButtonsSectionContainer",
                    "propertyName": "items",
                    "values": {
                        "controlConfig": {
                            "menu": {
                                "items": {
                                    "bindTo": "EnabledEditPages",
                                    "bindConfig": {
                                        "converter": function(editPages) {
                                            if (editPages.getCount() > 1) {
                                                return editPages;
                                            } else {
                                                return null;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            ]/**SCHEMA_DIFF*/
        };
    }
);

 

Like 0

Like

Share

0 comments
Show all comments

Question

How do I configure the frequency of automatic data synchronization in a mobile application?

Answer

The mobile application supports three types of synchronization:



Offline - to perform synchronization, you must click the sync button.

Offline synchronization in the background - starts when the bpm’online mobile application is minimized and only if the “Automatic synchronization” setting corresponds to the current status of the Internet connection.

Online - synchronization occurs during every interaction with a record in the mobile appication.

About filters that apply to displayed activities:

  • Activity must not be closed
  • Non-email activity
  • The user of the mobile application is in the activities.

Also, the filters of the mobile application interface are applied:

Activity date - depending on the filter set by date

"Display in schedule" checkbox

Like 0

Like

Share

0 comments
Show all comments
knowledge base
SDK
Q&A
support

Question 

I have a problem with uploading images after adding the standard functionality of "Notes". Notes are added to a detail. A separate object is created for the detail. Notes are added to the detail page schema as follows: the text is saved, images are not even uploaded. The insertImagesToNotes  method is not executed. Why?

Answer

The base detail, which all the rest of details are inherited from, does not have the necessary attributes, methods and mixins. Unlike pages that are inherited from BaseModulePageV2.

You can fix this by viewing at what has been implemented in BaseModulePageV2 and reproducing it in your detail. Create the detail object based on Base object with notes (Base) and create a detail based on this object via the detail wizard.

Add the following in the configurator page schema:

1. Dependency of requirejs from NotesUtilities ;

2. The following attribute:

attributes: {
    "NotesImagesCollection": {dataValueType:Terrasoft.DataValueType.COLLECTION}
},

3. The mixin:

mixins: {
    NotesUtilities: "Terrasoft.NotesUtilities"
},

4. The methods:

methods: {
        onNotesImagesUploadComplete: function() {
                this.hideBodyMask();
                this.updateFileDetail();
        },
        onNotesImagesUpload: function() {
                this.showBodyMask();
        },
        init: function(callback, scope) {
                this.callParent(arguments);
               this.mixins.NotesUtilities.initNotesImagesCollection.call(this);
        }
},

5. The notes field in the diff property:

{
        "operation": "insert",
        "parentName": "Header",
        "propertyName": "items",
        "name": "Notes",
        "bindTo": "Notes",
        "values": {
                contentType: Terrasoft.ContentType.RICH_TEXT,
                "layout" : {column: 0, row: 1, colSpan: 24},
                "controlConfig": {
                        "imageLoaded": {
                                "bindTo": "insertImagesToNotes"
                        },
                        "images": {
                                "bindTo": "NotesImagesCollection"
                        }
                }
        },
        "index": 1
}

The test schema code for the detail edit page:

define("UsrUsrMyDetail1Page", ["NotesUtilities"], function() {
	return {
		entitySchemaName: "UsrMyDetail",
		details: {},
		attributes: {
			"NotesImagesCollection": {dataValueType: Terrasoft.DataValueType.COLLECTION}
		},
		mixins: {
			NotesUtilities: "Terrasoft.NotesUtilities"
		},
		diff: [{
			"operation": "insert",
			"name": "UsrIntbcb7788a-2890-4358-bff3-102e82ea7889",
			"values": {
				"layout": {
					"colSpan": 12,
					"rowSpan": 1,
					"column": 0,
					"row": 0,
					"layoutName": "Header"
				},
				"labelConfig": {},
				"enabled": true,
				"bindTo": "UsrInt"
			},
			"parentName": "Header",
			"propertyName": "items",
			"index": 0
		},
		{
			"operation": "insert",
			"parentName": "Header",
			"propertyName": "items",
			"name": "Notes",
			"bindTo": "Notes",
			"values": {
				contentType: Terrasoft.ContentType.RICH_TEXT,
				"layout" : {column: 0, row: 1, colSpan: 24},
				"controlConfig": {
					"imageLoaded": {
						"bindTo": "insertImagesToNotes"
					},
					"images": {
						"bindTo": "NotesImagesCollection"
					}
				}
			},
			"index": 1
		}],
		methods: {
			onNotesImagesUploadComplete: function() {
				this.hideBodyMask();
				this.updateFileDetail();
			},
			onNotesImagesUpload: function() {
				this.showBodyMask();
			},
			init: function(callback, scope) {
				this.callParent(arguments);
				this.mixins.NotesUtilities.initNotesImagesCollection.call(this);
			}
		},
		rules: {}
	};
});

 

Like 0

Like

Share

0 comments
Show all comments

Question

How can I filter a field by the "Exists " filter with a parameter (another field value)?

Answer

Example of implementation the "Exists " filter:

var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
    "rootSchemaName": "Account"
});
// add the request columns
esq.addColumn("Id");
...
// filtering condition for using inside of "exists"
// searchValue - value for comparing with the SearchNumber column
var subFilters = Terrasoft.createFilterGroup();
subFilters.addItem(Terrasoft.createColumnFilterWithParameter(
    Terrasoft.ComparisonType.EQUAL, "SearchNumber", searchValue));
// add the exists-filter with a condition to the esq filter collection
var filters = esq.filters;
filters.add(Terrasoft.createExistsFilter("[AccountCommunication:Account:Id].Id", subFilters));
//receive the request value
esq.getEntityCollection(function(result) {
...
}, this);

As a result, the following request will be sent to the server:

SELECT Id, ... FROM Account
WHERE EXISTS 
(SELECT
[SubAccountCommunication].[Id] [Id]
FROM
[dbo].[AccountCommunication] [SubAccountCommunication] WITH(NOLOCK)
WHERE
[SubAccountCommunication].[AccountId] = [Account].[Id]
AND [SubAccountCommunication].[SearchNumber] = @P1
)

The @P1 parameter will store the searchValue value passed over to the filtering condition.

Like 1

Like

Share

0 comments
Show all comments
knowledge base
Q&A
support
SDK

Question

How can I execute an SQL-query (reading, adding, deleting) in the database On-demand?

It can be useful if a user does not have access to database but needs to read or add some data in the table.

Answer

Import the schema from the attached file. Publish and run it.

File attachments
Like 0

Like

Share

0 comments
Show all comments
knowledge base
SDK
Q&A
support

Case

Enable approval functionality for a new section

Solution

1. Create a new object for the [Approvals] custom section. The detail object name is generated from the section object name + Visa. For example, for the UsrInnerRequest  section, the object name will be UsrInnerRequestVisa. When creating the object, ensure inheriting from the [BaseVisa] object, add a field for connecting to the section, other parameters should be configured similar to the [OrderVisa] object. 

The UsrInnerRequest object should be managed by records.

2. Enable approval functionality for the custom section page. Namely, migrate all elements from the [OrderPageV2] order page schema to the custom section page by the Visa keyword.

3. Enable approving in the custom section list. Namely, migrate all elements from the [OrderSectionV2] order section list schema to the custom section list schema by the Visa key word.

4. Copy the "Receiving order approval" subprocess and change the Order and Read data parameters, as well as filtering of elements from the [Order] section to the custom section object. The subprocess title should look as follows: section name + VisaBaseSubprocess.

5.Copy the "Order approval" process and change the Order and Read data parameters, element filtering and the link to subprocess for the relevant values. The process title should look as follows: section name + VisaProcess. The elements of sending notifications should be changed for the new sending element.

6. Add a new "[custom section name] Approval process"  system setting with a link to the process specified in item 5. See the setup parameters in the "Order approval process" system setting.

To display approvals on the communication panel:

1. Copy the [OrderVisaNotificationProvider] schema and rename it for the Section name + VisaNotificationProvider. By the Order keyword, replace it in the schema for the name of the custom section object. The titles of the [Orders] section fields should be replaced by the corresponding fields of the custom section.

2. Register the previously added schema with the 0 type by a script in the [Notification Provider] table (the [Lookup] does not enable saving a record with a 0 type):

insert into NotificationProvider (ClassName, Type)
values ('Terrasoft.Configuration.UsrInnerRequestVisaNotificationProvider','0')

 

Like 3

Like

Share

0 comments
Show all comments
SDK
support
cases

1) Create client module

define("GlbHtmlEditModule", ["ext-base", "terrasoft", "HtmlEditModule"], function(Ext, Terrasoft) {
    Ext.define("Terrasoft.controls.GlbHtmlEdit", {
        extend: "Terrasoft.HtmlEdit",
        alternateClassName: "Terrasoft.GlbHtmlEdit",
         
        tplSignature: "
{0}: {1}", signature: false, setSignature: function(value) { if (this.signature === value) { return; } this.signature = value; }, onContentDom: function() { this.callParent(arguments); this.setSignature(false); var editor = this.editor; if (editor) { var editorDocument = this.editor.document; if (editorDocument) { var el = editorDocument.$; Ext.EventManager.on(el, "keypress", this.onKeyPress, this); } } }, destroy: function() { var editor = this.editor; if (editor) { var editorDocument = this.editor.document; if (editorDocument) { var el = editorDocument.$; Ext.EventManager.removeListener(el, "keypress", this.onKeyPress, this); } } this.callParent(arguments); }, onKeyPress: function(e) { if (!this.enabled || this.readonly) { return; } if (!this.signature && !e.isNavKeyPress() && !e.isSpecialKey()) { this.setSignature(true); var editor = this.editor; var selection = editor.getSelection(); var ranges = selection.getRanges(); var range = ranges[0]; var currentContact = Terrasoft.SysValue.CURRENT_USER_CONTACT.displayValue; var date = new Date(); var culture = Terrasoft.SysValue.CURRENT_USER_CULTURE ? Terrasoft.SysValue.CURRENT_USER_CULTURE.displayValue : ""; var signatureHtml = Ext.String.format(this.tplSignature, currentContact, date.toLocaleString(culture)); var signatureNode = CKEDITOR.dom.element.createFromHtml(signatureHtml); range.deleteContents(); range.select(); range.insertNode(signatureNode); var cursorNode = range.getNextNode(); range.selectNodeContents(cursorNode); selection.selectRanges(ranges); } } }); });

 

2) On the poge add dependency GlbHtmlEditModule and in diff section change className for your field (Example: Field Notes on Contact page):

{
    "operation": "merge",
    "parentName": "NotesControlGroup",
    "propertyName": "items",
    "name": "Notes",
    "values": {
        "className": "Terrasoft.GlbHtmlEdit"
    }
}

 

3) Result

Like 1

Like

Share

0 comments
Show all comments
SDK
support
cases
oData
package cherniak.bpmonline.com;
import java.io.OutputStream;
import java.net.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Attr;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
/**
* OData insert request for bpmonline
*
*/
public class App
{
    private static final String SERVICE_URL = "http://int-                web/Amdocs_T/0/ServiceModel/EntityDataService.svc/";
    private static final String AUTH_URL = "http://int-web/Amdocs_T/ServiceModel/AuthService.svc/Login";
    private static final String DS = "http://schemas.microsoft.com/ado/2007/08/dataservices";
    private static final String DSMD = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata";
    private static final String ATOM = "http://www.w3.org/2005/Atom";
    public static void main( String[] args ) throws Exception
    {
        CookieManager msCookieManager = new CookieManager();
        CookieHandler.setDefault(msCookieManager);
        if(GetAuthCookie("Supervisor", "Supervisor")) {
            CreateBpmEntityByOdataHttpExample(msCookieManager);
        }
    }
    public static boolean GetAuthCookie(String login, String password) {
        try{
            URL urlAuth = new URL(AUTH_URL);
            HttpURLConnection connection1Auth = (HttpURLConnection) urlAuth.openConnection();
            connection1Auth.setDoOutput(true);
            connection1Auth.setRequestMethod("POST");
            connection1Auth.setRequestProperty("Content-Type","application/json");
            String authJson = String.format("{\"UserName\": \"%s\", \"UserPassword\":\"%s\"}", login, password);
            byte[] outputBytes = authJson.getBytes("UTF-8");
            OutputStream os = connection1Auth.getOutputStream();
            os.write(outputBytes);
            os.close();
            int responseCode = connection1Auth.getResponseCode();
            return responseCode == 200;
        } catch (Exception e) {
            return false;
        }
    }
    public static void CreateBpmEntityByOdataHttpExample(CookieManager manager) {
        try{
            //Create xml document
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
            Document doc = docBuilder.newDocument();
            Element entry = doc.createElement("entry");
            Attr attrAtom = doc.createAttribute("xmlns");
            attrAtom.setValue(ATOM);
            entry.setAttributeNode(attrAtom);
            doc.appendChild(entry);
 
            Element content = doc.createElement("content");
            Attr attrType = doc.createAttribute("type");
            attrType.setValue("application/xml");
            content.setAttributeNode(attrType);
            entry.appendChild(content);
 
            Element properties = doc.createElement("properties");
            Attr attrMetadata = doc.createAttribute("xmlns");
            attrMetadata.setValue(DSMD);
            properties.setAttributeNode(attrMetadata);
            content.appendChild(properties);
 
            //Set Name of Contact
            Element name = doc.createElement("Name");
            Attr attrProp = doc.createAttribute("xmlns");
            attrProp.setValue(DS);
            name.setAttributeNode(attrProp);
            name.appendChild(doc.createTextNode("Test Person"));
            properties.appendChild(name);
 
            //Set Dear of Contact
            Element dear = doc.createElement("Dear");
            Attr attrOppo = doc.createAttribute("xmlns");
            attrOppo.setValue(DS);
            dear.setAttributeNode(attrOppo);
            dear.appendChild(doc.createTextNode("Mister"));
            properties.appendChild(dear);
 
            doc.setXmlStandalone(true);
 
            //Send insert request
            URL url = new URL(SERVICE_URL + "ContactCollection/");
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoOutput(true);
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Accept", "application/atom+xml");
            connection.setRequestProperty("Content-Type","application/atom+xml;type=entry");
 
            //Add BPMCSRF
            for(HttpCookie cookie : manager.getCookieStore().getCookies()) {
                if(cookie.getName().equals("BPMCSRF")) {
                    connection.setRequestProperty("BPMCSRF", cookie.getValue());
                }
            }
            OutputStream os = connection.getOutputStream();
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer transformer = tf.newTransformer();
            transformer.transform(new DOMSource(doc), new StreamResult(os));
            os.close();
            int responseCode = connection.getResponseCode();
            System.out.println(responseCode);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

 

Like 0

Like

Share

0 comments
Show all comments