Hello,



I've made a page with Creatio Freedom UI and need to be able to have 1 button on the page that both adds a record and then redirects the user to a specific page.  It appears I can only have the button do 1 action or the other (save a record or open a specific page).  To do both actions with one button, I instead tried creating a business process for this.  It's adding the record fine but I am having trouble getting it to open a specific page afterwards.  Opening an edit page and choosing the home page I want the user to be directed to does not work and instead.  I think it's because edit pages on a business process are treated like tasks and are not simply a redirect. 



Should I use a script element instead to redirect the user to a specific page after the record is added in the business process or is there a more simple way to do this?

Like 0

Like

1 comments

Hello community!

When we create a Business Process is there C#  code generated automatically that relates to that process ?

If so where and how can I find it ?

I need the answer for debugging purposes.sa

Thank you

Sasori

Like 0

Like

2 comments

Good day,

 

Thank you for your question.

If you are using some custom methods or functions in the business processes, your code should be displayed in the source code of the process:

 

Thank you.

Thank you very much for the response Artem!

I can not see the code that is generated behind the Low-Code elements like 'Add Data' for example ?

Where is that code located , or is it generated during runtime ?

Sasori

Show all comments

Hello

I have this code that checks is a contact/account is inactive or has all the required fields filled in. If this is true, then the user is not allowed to create a new activity.

I need to add another condition for fields in account: if Customer type = "Related account" AND Customer code is not filled in -> the user is not allowed to create a new activity.

Does anybody know how I can do this?

I tried to write it like this but I think that it doesn't read my fields properly.

Thank you!

Like 0

Like

1 comments

Hello,

 

You can review the process in the Activity object from the Exchange package and the UpdateContactAndAccountByParticipant method in it:

If you need to compare actual IDs you can either specify them as new Guid("Id value here") or create a separate source code and specify values there and use this separate source code (like it's done in the DoCollectEmailParticipants method using ActivityConsts source code):

and

Show all comments

Hi guys,

I am working on a custom "ContactFieldConverter" [the thing that splits the Contact's FullName imported by excel/ webserveces etc] in order to split new contact's names into "GivenName" and "Surname", and preventing the OOTB function from filling in the "MiddleName" column.

In order to do so, I created a custom ContactGsFieldConverter in my package and inserted the value of the Separator and Converter in the Lookup "ShowNamesBy" and sysSetting "ContactFieldConverter".

[myContactGsFieldConverter code:]

 

 namespace Terrasoft.Configuration {
	using System;
	using System.Linq;
	using System.Text;
	using Terrasoft.Common;
	using Terrasoft.Configuration;
 
	#region Class: myContactGsFieldConverter
 
	/// <summary>
	/// Contact "Full name" field converter class.
	/// Separates "Full name" string using "Given name Surname" rule.
	/// </summary>
	public class myContactGsFieldConverter : IContactFieldConverter
	{
 
		#region Properties: Public
 
		/// <summary>
		/// Contact "Full name" separator characters array.
		/// </summary>
		private char[] _separator = { ' ' };
		public char[] Separator {
			get {
				return _separator;
			}
			set {
				_separator = value;
			}
		}
 
		#endregion
 
		#region Methdos: Public
 
		/// <summary>
		/// <see cref="IContactFieldConverter.GetContactSgm"/>
		/// </summary>
		/// <remarks>
		/// After splitting <paramref name="name"/> first element will be used as <see cref="ContactSgm.GivenName"/>,
		/// Everything else as <see cref="ContactSgm.Surname"/>.
		/// </remarks>
		ContactSgm IContactFieldConverter.GetContactSgm(string name) {
			var sgm = new ContactSgm();
			if (string.IsNullOrEmpty(name)) {
				return sgm;
			}
 
			var array = name.Split(Separator, StringSplitOptions.RemoveEmptyEntries);
			switch (array.Length) {
				case 0:
					return sgm;
				case 1:
					sgm.GivenName = array[0];
					break;
				case 2:
					sgm.GivenName = array[0];
					sgm.Surname = array[1];
					break;
				default:
					sgm.GivenName = array[0];
					StringBuilder sb = new StringBuilder();
					for (var i = 1; i <= array.Length - 1; i++) {
						sb.AppendFormat("{0} ", array[i]);
					}
					sgm.Surname = sb.ToString().Trim();
					break;
			}
			return sgm;
		}
 
		/// <summary>
		/// <see cref="IContactFieldConverter.GetContactName"/>
		/// </summary>
		/// <remarks>
		/// "Full name" string will be created using "Given name [Middle name] Surname" rule.
		/// </remarks>
		public string GetContactName(ContactSgm sgm) {
			var concatChar = Separator.FirstOrDefault();
			return new[] { sgm.GivenName, sgm.MiddleName, sgm.Surname }.ConcatIfNotEmpty(concatChar.ToString());
		}
		#endregion
	}
	#endregion	
}

The converter is not working. I tried to debug and noticed that my contact converter is returned as null to [this is a method in the Contact c# object]: 

public virtual void SetSgm(Contact contact) {
			if (contact == null) {
				return;
			}
			contact.FillSgmFields(GetContactConverter());
		}

Do you know if I need to do something specific in case of separate-assembly package?

ie: Using a different namespace for the converter/ setting the converter path in a different way within the system setting/ recreate the method on the Contact Object in my custom package.





Thank you in advance!

Like 0

Like

4 comments

Hello Federica,

 

I just completed the test - convertor works in the assembly package as well. The code (since we don't need middle name) was:

namespace Terrasoft.Configuration {
    using System;
    using System.Linq;
    using System.Text;
    using Terrasoft.Common;
    #region Class: UsrCustomContactFieldConverter
    /// &lt;summary&gt;
    /// Contact "Full name" field converter class.
    /// Separates "Full name" string using "Surname Given name" rule.
    /// &lt;/summary&gt;
    public class UsrCustomContactFieldConverter : IContactFieldConverter
    {
        #region Properties: Public
        /// &lt;summary&gt;
        /// Contact "Full name" separator characters array.
        /// &lt;/summary&gt;
        private char[] _separator = { ' ' };
        public char[] Separator {
            get {
                return _separator;
            }
            set {
                _separator = value;
            }
        }
        #endregion
        #region Methdos: Public
        /// &lt;summary&gt;
        /// &lt;see cref="IContactFieldConverter.GetContactSgm"/&gt;
        /// &lt;/summary&gt;
        /// &lt;remarks&gt;
        /// After splitting &lt;paramref name="name"/&gt; first element will be used as &lt;see cref="ContactSgm.Surname"/&gt;,
        /// second element as &lt;see cref="ContactSgm.GivenName"/&gt;
        /// &lt;/remarks&gt;
        ContactSgm IContactFieldConverter.GetContactSgm(string name) {
			var sgm = new ContactSgm();
			if (string.IsNullOrEmpty(name)) {
				return sgm;
			}
			var array = name.Split(Separator, StringSplitOptions.RemoveEmptyEntries);
			switch (array.Length) {
				case 0:
					return sgm;
				case 1:
					sgm.GivenName = array[0];
					break;
				default:
					sgm.GivenName = array[0];
					sgm.Surname = array[1];
					break;
			}
			return sgm;
		}
        /// &lt;summary&gt;
        /// &lt;see cref="IContactFieldConverter.GetContactName"/&gt;
        /// &lt;/summary&gt;
        /// &lt;remarks&gt;
        /// "Full name" string will be created using "Surname Given name" rule.
        /// &lt;/remarks&gt;
        public string GetContactName(ContactSgm sgm) {
            var concatChar = Separator.FirstOrDefault();
            return new[] { sgm.Surname, sgm.GivenName }.ConcatIfNotEmpty(concatChar.ToString());
        }
        #endregion
    }
    #endregion
 
}

and then this convertor was registered in the database (ShowNamesBy table). As a result newly created contacts where full name is Test 1 2 had the first (Test) and last (1) name only while middle name was skipped.

Hi Oleg Drobina,

Could you share with me the record registered in the database table ShowNamesBy for a separate assembly pkg?

Hence, in case the site receives a Contact "Name": "Federica Rose Cattani" I don't want to "lose" the "MiddleName" but I want it to be concat to the "Surname". That's what I did in the converter shared. 

Federica,

 

Hi,

 

Sorry, I guess I was wrong with the package. Tested the same approach today and it didn't work until I unchecked the "Compile into separate assembly" checkbox in the package settings. So in your case you need to also do the same to make the converter work.

 

The insert was:

INSERT INTO ShowNamesBy (Name, Separator, Converter) VALUES (N'UsrCustomContactFieldConverter', N' .,;', N'Terrasoft.Configuration.UsrCustomContactFieldConverter');

 

Oleg Drobina,

Ok! In my case I can't "undo" the separate assembly since it contains customer's implementation and separate assembly it's way faster to compile.

The actual possible workaround would be to implement a second package without separate assembly containing only the custom ContactGsFieldConverter, am I correct?

Show all comments

Hi all

I have created a web service that accepts values from a third party server. Next, I need to transfer one value from the request to the section field.

Question:

How do I call my finished web service in C#?

Like 0

Like

4 comments

Hi,

Are you talking about a service created in the configuration or in the "Web services" section?

Dmytro Vovchenko, in the web services section

 

the question is how to set up its call in c#, so that in the future to use its result in one of the fields of the section

 

Alexandr Bezbozhnov,

As far as I know, currently, there is no direct way of running this sort of web service from code. However, you can run it inside a business process and you can run this process inside C# code using

ProcessEngineService.svc, with it you even can get the result values of the process.

Show all comments

Hi everyone,

how to use filter month and year Esq Server (EntitySchemaQuery)?

SELECT 
* 
FROM UsrTable 
WHERE 
MONTH(CreatedOn) = 1 AND YEAR(CreatedOn) = 2022

I found there is a function at https://academy.creatio.com/api/netcoreapi/7.17.0/#Terrasoft.Core~Terrasoft.Core.Entities.EntitySchemaQuery~CreateMonthFunction.html for get month and year.

https://prnt.sc/8brMGtYq3qhP

But how to use in filter?

esq.Filters.Add(esq.CreateFilterWithParameters(FilterComparisonType.Equal, "CreatedOn", Month));
esq.Filters.Add(esq.CreateFilterWithParameters(FilterComparisonType.Equal, "CreatedOn", Year));

Thank you.

Like 1

Like

1 comments
Best reply

Hello Romadan,

You can do filters like this using macros: 

// CreatedOn is the 1st month (January)
esq.Filters.Add(esq.CreateFilter(FilterComparisonType.Equal, "CreatedOn", EntitySchemaQueryMacrosType.Month, 1));
 
// CreatedOn is the first day of the month
esq.Filters.Add(esq.CreateFilter(FilterComparisonType.Equal, "CreatedOn", EntitySchemaQueryMacrosType.DayOfMonth, 1));
 
// CreatedOn is in the year 2022
esq.Filters.Add(esq.CreateFilter(FilterComparisonType.Equal, "CreatedOn", EntitySchemaQueryMacrosType.Year, 2022));

Ryan

Hello Romadan,

You can do filters like this using macros: 

// CreatedOn is the 1st month (January)
esq.Filters.Add(esq.CreateFilter(FilterComparisonType.Equal, "CreatedOn", EntitySchemaQueryMacrosType.Month, 1));
 
// CreatedOn is the first day of the month
esq.Filters.Add(esq.CreateFilter(FilterComparisonType.Equal, "CreatedOn", EntitySchemaQueryMacrosType.DayOfMonth, 1));
 
// CreatedOn is in the year 2022
esq.Filters.Add(esq.CreateFilter(FilterComparisonType.Equal, "CreatedOn", EntitySchemaQueryMacrosType.Year, 2022));

Ryan

Show all comments

Hello Community,

 

We have a requirement for fetching all the column names of an object using source code.

 

I have taken this community post https://community.creatio.com/questions/get-title-columns-esq as reference and tried.

 

As per the article, the below code is used for fetching the column names after fetching the entity collection.

 titleColumnCaption = entity.Schema.Columns.GetByName("Title").Caption.Value;

But the code returns the null value.

 

Kindly let us know whether the above line of code is correct or not?

If not, suggest us an other way to achieve the functionality.

 

Thanks,

Sivaranjani

Like 0

Like

2 comments

Hello Sivaranjani,

 

It happens because the code above returns the "Title" column caption only and if your object doesn't have the column with such a name the result is null.

 

You need to use something like:

var columnCaptionsArray = activityEntity.Schema.Columns;
    foreach (var columnCaption in columnCaptionsArray)
    {
    	var captionForColumn = columnCaption.Caption.Value;
    }

and use the captionForColumn in your logic furhter.

 

Best regards,

Oscar

Oscar Dylan,

Thanks for the reply. The above code is working.

Show all comments

Hi,

I want to use function that are not included in System library/package.

I need to add the following in order to use the functions.

using System.Linq;

I tried adding this to the script but got an error message: " Feature 'using declarations' is not available in C# 7.3. Please use language version 8.0 or greater."

Is there a way to add the 'System.Linq' somewhere?

Thanks,

Chani

 

Like 0

Like

1 comments

Hi Chani,

 

This error means that either the .Net Framework version in your server where the app is hosted is not 4.7.2 and higher or .Net Core version is not 3.1.301 and higher. Also you need to double-check that all the required components were enabled in the IIS settings.

 

Best regards,

Oscar

Show all comments

Hi community,

 

When implementing a web service, I have a GET method with a parameter :

 

public int GetMethod(string name)

 

In this method, I did a query to get the age of the person in parameter :

 

var select = new Select(UserConnection)

     .Column("Age")

     .From("Contact")

     .Where("Contact", "Name").IsEqual(Column.Parameter(name)) as Select;

 

Then I save the age into an int var :

 

var age = select.ExecuteScalar();

 

return age;

 

The problem is the following :

 

How can I check if the name of a contact in the method parameter exsists in the DB or not ?

 

Example :

 

if(name != exists) {

   return 0;

} else {

  return age;

}

 

Thanks a lot.

 

Best regards,

Jonathan

Like 0

Like

4 comments
Best reply

Hi Jonathan,

 

Usually you use dataReader to get the value from your select query. What you can do is:

bool hasRecord = false;
using (DBExecutor executor = UserConnection.EnsureDBConnection()) {
using (IDataReader dataReader = select.ExecuteReader(executor)) {
  while (dataReader.Read()) {
    hasRecord  = true;
  }
 }
}
if(hasrecord){
  return age
}else{
  return 0
}

Or you can just set the default value of the age =0. Therefore if the dataReader does not return any record, the default value age (0) will be returned.



regards,

Cheng Gong

Hi Jonathan

 

Please add the next using -     

     using Terrasoft.Common;   

on the top of the page(if you didn't have this one). 

 

Then in the part of the code when you are trying to retrieve the age:

 

if (name.IsNullOrEmpty())

{

return 0;

}

else

{

return age;

}

 

Best Regards, 

 

Bogdan L.

Hi Jonathan,

 

Usually you use dataReader to get the value from your select query. What you can do is:

bool hasRecord = false;
using (DBExecutor executor = UserConnection.EnsureDBConnection()) {
using (IDataReader dataReader = select.ExecuteReader(executor)) {
  while (dataReader.Read()) {
    hasRecord  = true;
  }
 }
}
if(hasrecord){
  return age
}else{
  return 0
}

Or you can just set the default value of the age =0. Therefore if the dataReader does not return any record, the default value age (0) will be returned.



regards,

Cheng Gong

Bogdan Lesyk,

Thanks for your answer. It helped a lot !

Cheng Gong,

 

Your answer is really perfect ! Thanks a lot, i'll definitely save this snippet of code for my future implementations.

 

Regards,

Jonathan

Show all comments

Hi everyone,

I have created a script task to create new records from a csv.

I am trying to implement a method to search the db for a matching record and then update it (in case it exists).

The second part (the 'else' part, it's working fine) 

Does anybody know how to filter and search a DB table? What am I getting wrong?

 

 

void saveLine(string line, int rowNumber){

    if(rowNumber!=0)

    {

        string lineFormatted = line.Replace("\"", "");

        string[] lineSplitted = lineFormatted.Split(',');

        var LRNMBL = lineSplitted[0];

        var LRRIGA = lineSplitted[1];

        var LRDTBL = lineSplitted[3];

        var LRCANA = lineSplitted[6];

        // Creation of query instance with "Contact" root schema. 

       

        // An EntitySchemaQuery instance that accesses the UsrTestFTPCall table of the database.

        var esq = new EntitySchemaQuery(UserConnection.EntitySchemaManager, "UsrVedniteTestate");

        

       

        // Adding columns to the query.

        esq.AddColumn("UsrLRNMBL");

        esq.AddColumn("UsrLRRIGA");

        esq.AddColumn("UsrLRDTBL");

        esq.AddColumn("UsrLRCANA");

        // Filter the query data. according to LRNMBL and 

        var esqFirstFilter = esq.createColumnFilterWithParameters(Terrasoft.ComparisonType.EQUAL,"UsrLRNMBL", LRNMBL);

        var esqSecondFilter = esq.createColumnFilterWithParameters(Terrasoft.ComparisonType.EQUAL,"UsrLRRIGA", LRRIGA);

        

        esq.filters.logicalOperation = Terrasoft.LogicalOperatorType.AND;

        

        esq.filters.add("esqFirstFilter", esqFirstFilter);

        //esq.Filters.Add(esqSecondFilter);

          

      

        // Get the result of the query.

        var entities = esq.GetEntityCollection(UserConnection);

        // If the data is received.

        if (entities.Count > 0)//Record exists in the db --> update

        {

           var recordToUpd = entities[0];

           recordToUpd.SetColumnValue("UsrLRNMBL", LRNMBL);

           recordToUpd.SetColumnValue("UsrLRRIGA", LRRIGA);

           recordToUpd.SetColumnValue("UsrLRDTBL", LRDTBL);

           recordToUpd.SetColumnValue("UsrLRCANA", LRCANA);

        }

        else 

        {

            //the record doesn't exist --> Create one

               var TestObj = UserConnection.EntitySchemaManager.GetInstanceByName("UsrTestFTPCall").CreateEntity(UserConnection);

            //access the data position and assign it to its column

            TestObj.SetDefColumnValues();

            //Associate new column values to old Col values

            TestObj.SetColumnValue("UsrName", rowNumber.ToString());

            TestObj.SetColumnValue("UsrLRNMBL", LRNMBL);//riferimento testata di vendita

            TestObj.SetColumnValue("UsrLRRIGA", LRRIGA);//riferimento riga all'interno della stessa vendita

            TestObj.SetColumnValue("UsrLRDTBL", LRDTBL);

            TestObj.SetColumnValue("UsrLRCANA", LRCANA);

            TestObj.Save();

           }

    }

}

 

Like 0

Like

4 comments

Hello,

I don't see anywhere in the code where you're saving the updates made to the entity in recordToUpd. Try adding the following to have it save the values in the database:

recordToUpd.UpdateInDB();

Ryan

Hello Federica,



Yes, try to add the method that Ryan recommended you. It will help to resolve the issue.



Best Regards,

Tetiana

Hi Ryan,

 

The problem is to access and filter records in the db.

That part of the script ain't working.

Hi Tetiana Bakai,

The main issue atm lays in the filtering and db-access part.

Show all comments