Business Process
EntityCollection
8.1.3
Sales_Creatio_enterprise_edition
8.0

I'm trying to get the "Resulting collection" out of a Read data step in a Business Process in order to iterate over it, but whatever I try the "Resulting collection" is null/empty when trying to access it later in BP. The "Collection of records" parameter for the step is populated with the expected number of records, but since it's an ICompositeObjectList, it can't be iterated over using an index (e.g. entityCollection[0]) which is really what I would like for this solution - using a foreach loop in code isn't ideal, as then we have to write everything in code rather than using the no code BP steps available to us.

 

I've tried many things including changing packages to not compile into a separate assembly and using the Resulting collection parameter in a subprocess BP by binding the output param to a BP param, and have even checked in the ReadDataUserTask code using Visual Studio to debug and check values, and it seems that the ResultEntityCollection ("Resulting collection") is being set correctly there, but it just doesn't seem to make it back to the Business Process. Does anyone know why this might be the case? And if there's any resolution? Currently working in 8.1.3

Like 1

Like

3 comments

To add some details to what I'm seeing, this is the Read data step:

 

This is a formula step to try to see what should be coming out of this step in the Resulting collection:

 

And this is my User Task step which takes an EntityCollection parameter:

 

Before the Formula step, the value of the "Entity collection" parameter is null, afterwards it appears in the BP trace logs as being "", so something does change - below is shown what the User Task step's Inspect looks like after it fails:

 

So the BP parameter value is "" for the EntityCollection, but it's null for passing into the User Task, and that's what we see in the User Task debugging in Visual Studio (which causes the error, as we get an "Object reference not set to an instance of an object" error when trying to use it).

 

When checking what the OOTB ReadDataUserTask code is setting to the ResultEntityCollection parameter (which is the parameter for "Resulting collection") we can see that it is correctly being passed the EntityCollection:

 

It just doesn't seem to be able to be used afterwards in the BP.

Anyone have any knowledge on why the Resulting collection parameter from a Read data step in a BP would be null despite it seeming to come back populated from the C# code?

Hello,

 

Just to clarify, does this not work even in the case when the collection is passed to a subprocess — does the same error occur in that scenario as well?

Show all comments
Business Process
calculate
field
Sum
Sales_Creatio_enterprise_edition
8.0

Hello all,

I am currently trying to update the standard Invoice object record's field; "payment amount" with a calculated sum collected from a custom object called: "Payments" from it's "Amount" field.

-Payments Record Added has the filter conditions of, "Amount is filled in"
- Payments Record Deleted has no filters
- Payments Record Modified has the, "Changes expected in any selected fields = 'Amount'"
 

 

 


 


And this is the current Invoice Record:

 

The Payment Amount field AND the test payment amount field I created show no input despite refreshes and alterations. I would appreciate any suggestions on my wrongdoings, as this is a more fundamental business process I have used before.

Thank you in advance for any help you can provide.

Like 0

Like

4 comments

Additionally, I found that the "read data" element is not actually picking up the invoice. Below is the trace data of the process log:


{
    "Element parameters": [
        {
            "Parameter": "Data source of filters",
            "Value": {
                "Before execution": "{\"className\":\"Terrasoft.FilterGroup\",\"serializedFilterEditData\":\"{\\\"className\\\":\\\"Terrasoft.FilterGroup\\\",\\\"items\\\":{\\\"e9bc0ff2-a863-446d-8673-b7c8a71ae2c3\\\":{\\\"className\\\":\\\"Terrasoft.CompareFilter\\\",\\\"filterType\\\":1,\\\"comparisonType\\\":3,\\\"isEnabled\\\":true,\\\"trimDateTimeParameterToDate\\\":false,\\\"leftExpression\\\":{\\\"className\\\":\\\"Terrasoft.ColumnExpression\\\",\\\"expressionType\\\":0,\\\"columnPath\\\":\\\"Id\\\"},\\\"isAggregative\\\":false,\\\"key\\\":\\\"e9bc0ff2-a863-446d-8673-b7c8a71ae2c3\\\",\\\"dataValueType\\\":0,\\\"leftExpressionCaption\\\":\\\"Id\\\",\\\"rightExpression\\\":{\\\"className\\\":\\\"Terrasoft.ParameterExpression\\\",\\\"expressionType\\\":2,\\\"parameter\\\":{\\\"className\\\":\\\"Terrasoft.Parameter\\\",\\\"dataValueType\\\":26,\\\"value\\\":{\\\"value\\\":\\\"[IsOwnerSchema:false].[IsSchema:false].[Element:{293bb23f-d16f-4c7a-ad45-9499a22ce47c}].[Parameter:{86b49173-d922-4022-b289-93b2acf6e683}]\\\",\\\"displayValue\\\":\\\"Payments Record Added.Unique identifier of record\\\"}}}},\\\"704c93a5-e747-4fcf-86b6-b14f1398ffe0\\\":{\\\"className\\\":\\\"Terrasoft.CompareFilter\\\",\\\"filterType\\\":1,\\\"comparisonType\\\":3,\\\"isEnabled\\\":true,\\\"trimDateTimeParameterToDate\\\":false,\\\"leftExpression\\\":{\\\"className\\\":\\\"Terrasoft.ColumnExpression\\\",\\\"expressionType\\\":0,\\\"columnPath\\\":\\\"Id\\\"},\\\"isAggregative\\\":false,\\\"key\\\":\\\"704c93a5-e747-4fcf-86b6-b14f1398ffe0\\\",\\\"dataValueType\\\":0,\\\"leftExpressionCaption\\\":\\\"Id\\\",\\\"rightExpression\\\":{\\\"className\\\":\\\"Terrasoft.ParameterExpression\\\",\\\"expressionType\\\":2,\\\"parameter\\\":{\\\"className\\\":\\\"Terrasoft.Parameter\\\",\\\"dataValueType\\\":26,\\\"value\\\":{\\\"value\\\":\\\"[IsOwnerSchema:false].[IsSchema:false].[Element:{32a3cb4b-4109-4978-84ae-e4f236ffddc6}].[Parameter:{a8f68505-7f8e-4e33-ac3d-3c9116eb1915}]\\\",\\\"displayValue\\\":\\\"Payments Record Deleted.Unique identifier of record\\\"}}}},\\\"d3db370d-afe3-49c5-a121-571f02715f64\\\":{\\\"className\\\":\\\"Terrasoft.CompareFilter\\\",\\\"filterType\\\":1,\\\"comparisonType\\\":3,\\\"isEnabled\\\":true,\\\"trimDateTimeParameterToDate\\\":false,\\\"leftExpression\\\":{\\\"className\\\":\\\"Terrasoft.ColumnExpression\\\",\\\"expressionType\\\":0,\\\"columnPath\\\":\\\"Id\\\"},\\\"isAggregative\\\":false,\\\"key\\\":\\\"d3db370d-afe3-49c5-a121-571f02715f64\\\",\\\"dataValueType\\\":0,\\\"leftExpressionCaption\\\":\\\"Id\\\",\\\"rightExpression\\\":{\\\"className\\\":\\\"Terrasoft.ParameterExpression\\\",\\\"expressionType\\\":2,\\\"parameter\\\":{\\\"className\\\":\\\"Terrasoft.Parameter\\\",\\\"dataValueType\\\":26,\\\"value\\\":{\\\"value\\\":\\\"[IsOwnerSchema:false].[IsSchema:false].[Element:{335bd2a9-757f-4750-adb1-a6d1a23e05f1}].[Parameter:{c6326280-12ce-424f-830a-9659100f8272}]\\\",\\\"displayValue\\\":\\\"Payments Record Modified.Unique identifier of record\\\"}}}}},\\\"logicalOperation\\\":0,\\\"isEnabled\\\":true,\\\"filterType\\\":6,\\\"rootSchemaName\\\":\\\"IWPayments\\\",\\\"key\\\":\\\"\\\"}\",\"dataSourceFilters\":\"{\\\"items\\\":{\\\"e9bc0ff2-a863-446d-8673-b7c8a71ae2c3\\\":{\\\"filterType\\\":1,\\\"comparisonType\\\":3,\\\"isEnabled\\\":true,\\\"trimDateTimeParameterToDate\\\":false,\\\"leftExpression\\\":{\\\"expressionType\\\":0,\\\"columnPath\\\":\\\"Id\\\"},\\\"rightExpression\\\":{\\\"expressionType\\\":2,\\\"parameter\\\":{\\\"dataValueType\\\":26,\\\"value\\\":{\\\"value\\\":\\\"[IsOwnerSchema:false].[IsSchema:false].[Element:{293bb23f-d16f-4c7a-ad45-9499a22ce47c}].[Parameter:{86b49173-d922-4022-b289-93b2acf6e683}]\\\"}}}},\\\"704c93a5-e747-4fcf-86b6-b14f1398ffe0\\\":{\\\"filterType\\\":1,\\\"comparisonType\\\":3,\\\"isEnabled\\\":true,\\\"trimDateTimeParameterToDate\\\":false,\\\"leftExpression\\\":{\\\"expressionType\\\":0,\\\"columnPath\\\":\\\"Id\\\"},\\\"rightExpression\\\":{\\\"expressionType\\\":2,\\\"parameter\\\":{\\\"dataValueType\\\":26,\\\"value\\\":{\\\"value\\\":\\\"[IsOwnerSchema:false].[IsSchema:false].[Element:{32a3cb4b-4109-4978-84ae-e4f236ffddc6}].[Parameter:{a8f68505-7f8e-4e33-ac3d-3c9116eb1915}]\\\"}}}},\\\"d3db370d-afe3-49c5-a121-571f02715f64\\\":{\\\"filterType\\\":1,\\\"comparisonType\\\":3,\\\"isEnabled\\\":true,\\\"trimDateTimeParameterToDate\\\":false,\\\"leftExpression\\\":{\\\"expressionType\\\":0,\\\"columnPath\\\":\\\"Id\\\"},\\\"rightExpression\\\":{\\\"expressionType\\\":2,\\\"parameter\\\":{\\\"dataValueType\\\":26,\\\"value\\\":{\\\"value\\\":\\\"[IsOwnerSchema:false].[IsSchema:false].[Element:{335bd2a9-757f-4750-adb1-a6d1a23e05f1}].[Parameter:{c6326280-12ce-424f-830a-9659100f8272}]\\\"}}}}},\\\"logicalOperation\\\":0,\\\"isEnabled\\\":true,\\\"filterType\\\":6,\\\"rootSchemaName\\\":\\\"IWPayments\\\"}\"}",
                "After execution": "{\"className\":\"Terrasoft.FilterGroup\",\"serializedFilterEditData\":\"{\\\"className\\\":\\\"Terrasoft.FilterGroup\\\",\\\"items\\\":{\\\"e9bc0ff2-a863-446d-8673-b7c8a71ae2c3\\\":{\\\"className\\\":\\\"Terrasoft.CompareFilter\\\",\\\"filterType\\\":1,\\\"comparisonType\\\":3,\\\"isEnabled\\\":true,\\\"trimDateTimeParameterToDate\\\":false,\\\"leftExpression\\\":{\\\"className\\\":\\\"Terrasoft.ColumnExpression\\\",\\\"expressionType\\\":0,\\\"columnPath\\\":\\\"Id\\\"},\\\"isAggregative\\\":false,\\\"key\\\":\\\"e9bc0ff2-a863-446d-8673-b7c8a71ae2c3\\\",\\\"dataValueType\\\":0,\\\"leftExpressionCaption\\\":\\\"Id\\\",\\\"rightExpression\\\":{\\\"className\\\":\\\"Terrasoft.ParameterExpression\\\",\\\"expressionType\\\":2,\\\"parameter\\\":{\\\"className\\\":\\\"Terrasoft.Parameter\\\",\\\"dataValueType\\\":26,\\\"value\\\":{\\\"value\\\":\\\"[IsOwnerSchema:false].[IsSchema:false].[Element:{293bb23f-d16f-4c7a-ad45-9499a22ce47c}].[Parameter:{86b49173-d922-4022-b289-93b2acf6e683}]\\\",\\\"displayValue\\\":\\\"Payments Record Added.Unique identifier of record\\\"}}}},\\\"704c93a5-e747-4fcf-86b6-b14f1398ffe0\\\":{\\\"className\\\":\\\"Terrasoft.CompareFilter\\\",\\\"filterType\\\":1,\\\"comparisonType\\\":3,\\\"isEnabled\\\":true,\\\"trimDateTimeParameterToDate\\\":false,\\\"leftExpression\\\":{\\\"className\\\":\\\"Terrasoft.ColumnExpression\\\",\\\"expressionType\\\":0,\\\"columnPath\\\":\\\"Id\\\"},\\\"isAggregative\\\":false,\\\"key\\\":\\\"704c93a5-e747-4fcf-86b6-b14f1398ffe0\\\",\\\"dataValueType\\\":0,\\\"leftExpressionCaption\\\":\\\"Id\\\",\\\"rightExpression\\\":{\\\"className\\\":\\\"Terrasoft.ParameterExpression\\\",\\\"expressionType\\\":2,\\\"parameter\\\":{\\\"className\\\":\\\"Terrasoft.Parameter\\\",\\\"dataValueType\\\":26,\\\"value\\\":{\\\"value\\\":\\\"[IsOwnerSchema:false].[IsSchema:false].[Element:{32a3cb4b-4109-4978-84ae-e4f236ffddc6}].[Parameter:{a8f68505-7f8e-4e33-ac3d-3c9116eb1915}]\\\",\\\"displayValue\\\":\\\"Payments Record Deleted.Unique identifier of record\\\"}}}},\\\"d3db370d-afe3-49c5-a121-571f02715f64\\\":{\\\"className\\\":\\\"Terrasoft.CompareFilter\\\",\\\"filterType\\\":1,\\\"comparisonType\\\":3,\\\"isEnabled\\\":true,\\\"trimDateTimeParameterToDate\\\":false,\\\"leftExpression\\\":{\\\"className\\\":\\\"Terrasoft.ColumnExpression\\\",\\\"expressionType\\\":0,\\\"columnPath\\\":\\\"Id\\\"},\\\"isAggregative\\\":false,\\\"key\\\":\\\"d3db370d-afe3-49c5-a121-571f02715f64\\\",\\\"dataValueType\\\":0,\\\"leftExpressionCaption\\\":\\\"Id\\\",\\\"rightExpression\\\":{\\\"className\\\":\\\"Terrasoft.ParameterExpression\\\",\\\"expressionType\\\":2,\\\"parameter\\\":{\\\"className\\\":\\\"Terrasoft.Parameter\\\",\\\"dataValueType\\\":26,\\\"value\\\":{\\\"value\\\":\\\"[IsOwnerSchema:false].[IsSchema:false].[Element:{335bd2a9-757f-4750-adb1-a6d1a23e05f1}].[Parameter:{c6326280-12ce-424f-830a-9659100f8272}]\\\",\\\"displayValue\\\":\\\"Payments Record Modified.Unique identifier of record\\\"}}}}},\\\"logicalOperation\\\":0,\\\"isEnabled\\\":true,\\\"filterType\\\":6,\\\"rootSchemaName\\\":\\\"IWPayments\\\",\\\"key\\\":\\\"\\\"}\",\"dataSourceFilters\":\"{\\\"items\\\":{\\\"e9bc0ff2-a863-446d-8673-b7c8a71ae2c3\\\":{\\\"filterType\\\":1,\\\"comparisonType\\\":3,\\\"isEnabled\\\":true,\\\"trimDateTimeParameterToDate\\\":false,\\\"leftExpression\\\":{\\\"expressionType\\\":0,\\\"columnPath\\\":\\\"Id\\\"},\\\"rightExpression\\\":{\\\"expressionType\\\":2,\\\"parameter\\\":{\\\"dataValueType\\\":26,\\\"value\\\":{\\\"value\\\":\\\"[IsOwnerSchema:false].[IsSchema:false].[Element:{293bb23f-d16f-4c7a-ad45-9499a22ce47c}].[Parameter:{86b49173-d922-4022-b289-93b2acf6e683}]\\\"}}}},\\\"704c93a5-e747-4fcf-86b6-b14f1398ffe0\\\":{\\\"filterType\\\":1,\\\"comparisonType\\\":3,\\\"isEnabled\\\":true,\\\"trimDateTimeParameterToDate\\\":false,\\\"leftExpression\\\":{\\\"expressionType\\\":0,\\\"columnPath\\\":\\\"Id\\\"},\\\"rightExpression\\\":{\\\"expressionType\\\":2,\\\"parameter\\\":{\\\"dataValueType\\\":26,\\\"value\\\":{\\\"value\\\":\\\"[IsOwnerSchema:false].[IsSchema:false].[Element:{32a3cb4b-4109-4978-84ae-e4f236ffddc6}].[Parameter:{a8f68505-7f8e-4e33-ac3d-3c9116eb1915}]\\\"}}}},\\\"d3db370d-afe3-49c5-a121-571f02715f64\\\":{\\\"filterType\\\":1,\\\"comparisonType\\\":3,\\\"isEnabled\\\":true,\\\"trimDateTimeParameterToDate\\\":false,\\\"leftExpression\\\":{\\\"expressionType\\\":0,\\\"columnPath\\\":\\\"Id\\\"},\\\"rightExpression\\\":{\\\"expressionType\\\":2,\\\"parameter\\\":{\\\"dataValueType\\\":26,\\\"value\\\":{\\\"value\\\":\\\"[IsOwnerSchema:false].[IsSchema:false].[Element:{335bd2a9-757f-4750-adb1-a6d1a23e05f1}].[Parameter:{c6326280-12ce-424f-830a-9659100f8272}]\\\"}}}}},\\\"logicalOperation\\\":0,\\\"isEnabled\\\":true,\\\"filterType\\\":6,\\\"rootSchemaName\\\":\\\"IWPayments\\\"}\"}"
            }
        },
        {
            "Parameter": "Read first",
            "Value": {
                "Before execution": true,
                "After execution": true
            }
        },
        {
            "Parameter": "Columns order",
            "Value": {
                "Before execution": "",
                "After execution": ""
            }
        },
        {
            "Parameter": "First item of resulting collection",
            "Value": {
                "Before execution": {},
                "After execution": {}
            }
        },
        {
            "Parameter": "Read uncommitted data",
            "Value": {
                "Before execution": true,
                "After execution": true
            }
        },
        {
            "Parameter": "Consider time in the filter",
            "Value": {
                "Before execution": true,
                "After execution": true
            }
        }
    ],
    "Process parameters": [
        {
            "Parameter": "IWPayments Amount",
            "Value": {
                "Before execution": 0,
                "After execution": 0
            }
        }
    ]
}

In the first read where you use the Id values from the start signals, change the AND to OR (if you click the AND it will toggle it to OR).

Ryan

Ryan Farley,

Thank you Ryan. I must have overlooked that detail while reviewing other work! I am now having a new issue where the calculation element shows an incorrect sum.

For instance, when setting the Calculate Element to, "OR" I will have one record with an amount of $4500. When modified, it will then show a sum of $94,500.

But if I set it to, "AND", then the Calculate Element will show $0 for both the input and output.

Any idea on what could be causing this?

 

I am going to answer my own question here for my reply, as I discovered that my filters were not working correctly and the calculated sum was adding ALL records of the Payments object:

 

I found that for the "Calculate Element" filters, not only did I not need the 

 

"id ≠ Payments.Record Deleted.Unique identifier of record" 

 

But that the filter of:

 

"Invoice = Read Invoice from IWPayments.First item of resulting collection.Invoice"

 

Should be:

 

"Invoice.Id = Read Invoice from IWPayments.First item of resulting collection.Invoice"

 

I thought I had set it to that already, but I must have overlooked it while troubleshooting other solutions. 

Thank you to anyone who took a look at this!

Show all comments
NewtonSoft.Json
webservice
serialize
Sales_Creatio_enterprise_edition
8.0

Hi Community,

 

We have this requirement, where we need to receive a complex json object and then store it in our database as a string, without using DataContracts.

 

To achieve this we though about using the "object" type and then serialize it into a string using JsonConvert.SerializeObject method. 

 

	  [OperationContract]
	  [WebInvoke(Method = "POST", UriTemplate = "/store", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
      public Response AddStore(object store) {

         Response response = new Response();
         response.MessageId = "1";
         response.Description = "Store Inserted!";

        string storeString = JsonConvert.SerializeObject(store, Formatting.Indented);

        var ins = new Insert(UserConnection)
        .Into("ImdStagingInArticle")
        .Set("ImdMessage", Column.Parameter(storeString))
        .Set("ImdStateId", Column.Parameter(new Guid("2d1dee23-058b-45fe-95a0-2e1612fc4261")));
        
        ins.Execute();
      
        return response;   
      }

 

However, the string is always empty. 

 

Since the json is to complex, the serializer cannot process the entire json data. 

 

We also tried to use WebOperationContext, but that doesn't work.

 

Can someone help us solve this issue? Did anyone have something similar?

 

Thank you.

Like 0

Like

7 comments

Hi,

 

First of all you need to make sure that you can convert the object into a string in general. Like create a Visual Studio project, add the logic to convert the object into a string using JsonSerializer like

 

string jsonString = JsonSerializer.Serialize(myObject); Console.WriteLine(jsonString);

 

And see the result. After the number of tests find the way when the data you pass is converted into the string and then start developing an additional logic of storing this data in the Creatio database using the insert query you used.

 

Alternatively find the way to make the object to have a constant set of keys so to be sure it will be converted to the string as needed.

Oleg Drobina,

 

After some changes I got it to work, by reading the raw body before the automatic parsing. However, this is working only on our Linux environment. As for for windows environment (Creatio Cloud), we are receiving some parse errors. 

 

      [OperationContract]
      [WebInvoke(Method = "POST", UriTemplate = "/article", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
      public Response AddArticle(string articleJson) {

        string result = "";
        Stream inputStream = HttpContext.Current.Request.Body;
        
        inputStream.Position = 0;
        using (StreamReader reader = new StreamReader(inputStream, Encoding.UTF8))
        {
            result = reader.ReadToEnd();
        }

        var parsedJson = JsonConvert.DeserializeObject(result);
        string jsonString = JsonConvert.SerializeObject(parsedJson, Formatting.Indented);

        



        Response response = new Response();
        response.MessageId = "1";
        response.Description = "Article Inserted!";



        var ins = new Insert(UserConnection)
        .Into("ImdStagingInArticle")
        .Set("ImdMessage", Column.Parameter(jsonString))
        .Set("ImdStateId", Column.Parameter(new Guid("2d1dee23-058b-45fe-95a0-2e1612fc4261")));
        ins.Execute();

        inputStream.Close();
      
        return response;  
      }

 

What could be the cause for such weird behaviour?

 

Thank you.
      

 

Pedro Pinheiro,

 

Well, it shouldn't happen. Maybe there is still some difference in the content we pass in the local machine and in the Windows machine?

Oleg Drobina,

 

The requests are the same for both local and cloud environments, except the address and credentials.

 

However, when I execute the request on the cloud environment I get this error:

 

 <p class="heading1">Request Error</p>
       <p>The server encountered an error processing the request. The exception message is 'This method or property is
           not supported after HttpRequest.GetBufferlessInputStream has been invoked.'. See server logs for more
           details. The exception stack trace is: </p>
       <p> at System.Web.HttpRequest.get_InputStream()
           at Terrasoft.Configuration.ImdArticleAPI.ArticleAPI.AddArticle(Object article)
           at SyncInvokeAddArticle(Object , Object[] , Object[] )
           at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]&amp;
           outputs)
           at Terrasoft.Web.Common.ServiceModel.ThreadContextInitializer.Invoke(Object instance, Object[] inputs,
           Object[]&amp; outputs)
           at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc&amp; rpc)
           at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc&amp; rpc)
           at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc&amp; rpc)
           at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)</p>

 

Have you encountered something similiar? What could be the cause for such error?

 

Thank you.

 

Pedro Pinheiro,

 

Creatio doesn’t know how to serialize/deserialize object. If you change object to string in Response AddStore(object store) you will be able to parse it with JsonParser of your choice.

Kirill Krylov CPA,

 

The problem is, if I change it to string I can only send strings to this endpoint (The Json must be converted to a string). Because, if I try to send a Json Object I get "400 Bad Request".

 

 

 

Hello everyone,

 

I managed to get it working by receiving the body as a Stream instead of a String.

 

With this solution, I don't get the "400 Bad request" and I can process any Json object.

 

I don't know if this is the best solution, but it's working for now.
 

	  [OperationContract]
      [WebInvoke(Method = "POST", UriTemplate = "/article", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
      public Response AddArticle(Stream requestBody) {
                
        string result = "";

        using (StreamReader reader = new StreamReader(requestBody, Encoding.UTF8))
        {
            result = reader.ReadToEnd();
        }

        var parsedJson = JsonConvert.DeserializeObject(result);
        string jsonString = JsonConvert.SerializeObject(parsedJson, Formatting.Indented);

        Response response = new Response();
        response.MessageId = "1";
        response.Description = "Article Inserted!";

        var ins = new Insert(UserConnection)
        .Into("ImdStagingInArticle")
        .Set("ImdMessage", Column.Parameter(jsonString))
        .Set("ImdStateId", Column.Parameter(new Guid("2d1dee23-058b-45fe-95a0-2e1612fc4261")));
        ins.Execute();

        return response;  
      }

 

Feel free to give any feedback on this solution.

 

Thank you.

 

Show all comments
forecasts
Sales_Creatio_enterprise_edition
8.0

Hi There, 

I'm trying to create a sales forecast. To create it I want to use figures from 2024. However the time periods for the columns need to be 2025. Is there a way I can see actual historic data? I.e January 2024 vs January 2025? 

The only way I found I can do this is by manually entering the 2024 data. However, given that I'm doing this for a number of different businesses it's very tedious. So for example in the period column for March 2025, I would like to see actual salees figures from March 2024, the forecasted amount (based on March 2024) followed by the Actual sales figures. 

 

I'm using Invoice owner acount to specify the different business units (rows) and Invoice created on filed to specify the time period. 

Thank you 

Like 0

Like

1 comments

Hello!

Unfortunately, the planning functionality is currently unable to process values from a previous period.

The described case is best solved with the help of the MP solution: https://marketplace.creatio.com/app/calculated-metrics-creatio. There it will be possible to output three indicators: Current Fact, Previous Fact, Percentage of the ratio of the current to the previous one.

Best regards,
Anton

Show all comments
QR Code scanner
custom_components
FreedomUI
Sales_Creatio_enterprise_edition
8.0

Hi Community,

 

Our customer has requested a bar code scanner inside Creatio, so they can scan products and check its information.

We have multiple ways of doing this:

 

  1. WebApp (Custom Component) that opens the smartphone camera;
  2. WebApp (Custom Component) that establishes a connection to a scanner device (for example a Zebra Scanner);
  3. Bar code scanner in the mobile app, which we will be able to configure as described here https://academy.creatio.com/docs/8.x/resources/release-notes/8-2-1-energy-release-notes#title-2782-13.

     

For our use case, we will be using the first option, since option three is not available at the moment.

 

After some digging, we discovered that there are multiple libraries that could help us implement this use case. However, we decided to post this question to know if someone has already implemented something similar, or at least tried to. So, we can share the know-how behind it.

 

Thank you.

Like 4

Like

5 comments

Have not tried, also looking forward to some knowhow. Not just to scan, but also to generate for event registrations for example. 

I have integrated a barcode scanner with Creatio. We've used a simple bluetooth barcode scanner connected to the device (in our case it was a tablet with full Creatio open in the browser). Most barcode scanners work just like a connected keyboard. When a barcode is scanned it sends the "text" value of the barcode to as input, just as if it were typed in. In my solution, we had a page that opened and we set focus to a text/input field on the page and dislayed some message about "waiting for barcode" for the user. Then, once scanned, the text value of the barcode scanned triggered a change event for the text/input field and we then did the action needed for the barcode (which in our case the barcode was a vehicle VIN, so we then used an API to get the vehicle details for the scanned VIN). All really simple to be honest. Using this approach, thinking of the barcode scanner as text entered by an input device, just like a keyboard, it all turned out to be really easy to work with.
Hope this helps.

Ryan.

Hey Community, 
Found this on the Creatio page 

Has anyone attempted to identify the exact code or reference methods that enable this feature? We're looking to leverage this capability for a client and are trying to figure it out.

Ryan Farley,

Hello, Looks like the barcode scan functionality has been released for Mobile version 8.2.4. Here is what Creatio sent us. Did anyone from community get a chance to try this?

BarcodeScanService is a service used to initiate the barcode scanner and retrieve the scan result using scan() method. Supported barcode types:

  • Aztec: ISO/IEC 24778 — 2D matrix barcode, compact, high data capacity, no quiet zone needed.
  • Code 39: ISO/IEC 16388 — Variable-length, alphanumeric, widely used in logistics and inventory.
  • Code 93: ISO/IEC 15417 — Higher density and reliability version of Code 39, supports more characters.
  • EAN: ISO/IEC 15420 — 1D barcode for retail products, encodes 12-13 digits, globally standardized.
  • Code 128: ISO/IEC 15417 — High-density 1D barcode, supports ASCII 128, used in shipping and logistics.
  • Data Matrix: ISO/IEC 16022 — 2D barcode, supports large data storage, error correction included.
  • QR: ISO/IEC 18004 — 2D matrix code, fast scanning, supports URLs, text, and more, error correction built-in.
  • ITF (Interleaved 2 of 5): ISO/IEC 16390 — Numeric-only, compact, used for cartons and packaging.
  • UPCE: ISO/IEC 15420 — Compressed version of UPC, for small products, 6-digit format.
  • PDF417: ISO/IEC 15438 — 2D stacked linear barcode, supports large data, used in documents and IDs.


 

Return data

type - Indicates the result type: barcode, error, or cancelled.

rawContent - The scanned barcode content; null if the scan is canceled or an error occurs.

errorMessage - Describes the error if an error occurs; null otherwise.

format - Specifies the barcode format (one of the supported types or unknown); null in case of an error.

Usage:

@CrtRequest({

    type: 'crt.TestBarcodeScanRequest',

})

export class TestBarcodeScanRequest extends BaseRequest { }

@CrtRequestHandler({

    requestType: 'crt.TestBarcodeScanRequest',

    type: 'usr.TestBarcodeScanRequest',

    scopes: ['MobileContact_ListPage']

})

export class TestCaseScanBarcodeRequestHandler extends BaseRequestHandler<TestBarcodeScanRequest> {

    public async handle(request: BaseRequest): Promise<unknown> {

        const res: BarcodeScanResult = await new BarcodeScanService().scan();

        Logger.console('___ Result type: ' + res.type);

        Logger.console('___ Content: ' + res.rawContent);

        Logger.console('___ Error: ' + res.errorMessage);

        Logger.console('___ Scanned code format: ' + res.format);

        return res;

    }

}

Hi there, I managed to make working example of QR code or barcode scanning in Creatio mobile application, as well as GPS data reading. The most challenging was to make proper code wrapper for your lines of code. You can find more details about this wrapper here:
Custom request handler for mobile app
Here is my example of index.ts file:

/* Import the required functionality from the libraries. */
import {
    BaseRequest,
    CrtRequest,
    BaseRequestHandler,
    CrtRequestHandler,
    Logger,
    CrtModule,
    bootstrapCrtModule,
    DoBootstrap,
 
    BarcodeScanService,
    BarcodeScanResult,
 
    GeolocationService,
    GeolocationServicePosition,
    GeolocationAccuracy
} from "@creatio/mobile-common";

 
/* Add the "CrtRequest" decorator to the "SomeRequestNameRequest" class. */
@CrtRequest({
    type: 'usr.SomeRequestNameRequest'
})
 
export class SomeRequestNameRequest extends BaseRequest {}
 
/* Add the "CrtRequestHandler" decorator to the "SomeRequestNameHandler" class. */
@CrtRequestHandler({
    requestType: 'usr.SomeRequestNameRequest',
    type: 'usr.SomeRequestNameHandler',
    scopes: ['MobileFUIContactRecordPageSettingsDefaultWorkplace'],
})
 
export class SomeRequestNameHandler extends BaseRequestHandler<SomeRequestNameRequest> {
 
    public async handle(request: SomeRequestNameRequest): Promise<unknown> {
 
        /* Implement a custom business logic to process scanned data. */
        // this is just an example of how you can read column value at mobile FreedomUI form page
        let name = await request.$context['Name']; 
        // note: you must add BarcodeScanService and BarcodeScanResult in your import code section
        const res: BarcodeScanResult = await new BarcodeScanService().scan();
        // set result value in Name column of Contact Form mobile FreedomUI Page, just visible proof of concept
        request.$context['Name'] = 'Scanned text: ' + res.rawContent;
 
        // note: you must add GeolocationService, GeolocationServicePosition and GeolocationAccuracy in your import code section
        const coords: GeolocationServicePosition = await new GeolocationService().getCurrentCoordinates(GeolocationAccuracy.low);
        // set resut values in Contact Form mobile FreedomUI Page, another visible proof of concept
        request.$context['Dear'] = "GPS coords: Lat:" + coords.latitude + ", long:" + coords.longitude;
        // visible proof that code successfully reaches this line
        request.$context['JobTitle'] = "GPS works!";
        return this.next?.handle(request);
    }
}

// It seems that this part is necessary to make this module work as JS source in File Content part of your Creatio package
@CrtModule({
    /* Specify that "SomeRequestNameHandler" is request handler. */
    requestHandlers: [
        SomeRequestNameHandler
    ]
})
 
export class SomeMainAppClass implements DoBootstrap {
    bootstrap(): void {
        bootstrapCrtModule('SomeMainAppClass', SomeMainAppClass);
    }
}

After running command npm run build in my TypeScript project folder I got .\out\mobile\DevModule\main.js file and manually copied it to my Creatio package file content destination: .\Terrasoft.WebApp\Terrasoft.Configuration\Pkg\UsrMyDemo\Files\src\mobile\SomeMainAppClass\main.js

This example is designed to be used with a Button added to Contact Form Page (FreedomUI) in Creatio mobile application. I set 

usr.SomeRequestNameRequest

as request name for my custom button. Here is code of my MobileFUIContactRecordPageSettingsDefaultWorkplace module:
 

[
	{
		"operation": "merge",
		"name": "settings",
		"values": {
			"localizableStrings": {
				"primaryColumnSetContact_caption": "Primary column set",
				"profileColumnSetContact_caption": "Profile",
				"infoColumnSetContact_caption": "Contact info",
				"ContactCareerDetailV2EmbeddedDetailContact_caption": "Job experience",
				"ContactAddressDetailV2EmbeddedDetailContact_caption": "Addresses",
				"ContactCommunicationDetailEmbeddedDetailContact_caption": "Communication options",
				"ContactTimelineTab_caption": "Timeline",
				"TabFeed_caption": "Feed",
				"TabAttachments_caption": "Attachments"
			},

            "entitySchemaName": "Contacts",
            "settingsType": "RecordPage",
            "columnSets": [],
            "operation": "insert",
            "details": [],
            "viewConfigDiff": "[{\"operation\":\"insert\",\"name\":\"SomeButton\",\"parentName\":\"Contact_PrimaryTab_Body_profileColumnSet\",\"propertyName\":\"items\",\"values\":{\"type\":\"crt.Button\",\"caption\":\"Button\",\"clicked\":{\"request\":\"usr.SomeRequestNameRequest\"}}}]"

			
 		}
	}

]

I am using Creatio 8.3.0.3074 and Creatio Mobile 8.3.4 for Android. I installed current version of Customer360 app into my Creatio system.

When I open any Contact in mobile app, click on my new Button, this code starts one-time barcode scanning and sets results into contact Name. Then code starts reading GPS coordinates and sets results into "Recipient's name" column.

I hope this code sample will help you to build your own Creatio Mobile customization to read QR codes or barcodes or to get GPS coordinates.
 

Show all comments
knowledge base
data binding
8.1.3
Sales_Creatio_enterprise_edition
8.0

Is it possible to bind knowledge base articles to packages, or in some other way move them between environments in an effective way? The client wants to be able to set up articles in their Pre environment and transfer them into Prod when ready, but the documentation doesn't provide information on the possibility of this.

 

It also might not be ideal to bind this data in a non-dev environment, since you will then have packages that must be created from non-dev environments to accomplish this, so perhaps there is another recommended way of moving such data between environments?

 

We are currently on 8.1.3, planning on upgrading to 8.2.1 soon, and are using exclusively Freedom UI sections.

Like 2

Like

2 comments

Hi Harvey

I recommend using an integration tool like Make.com to automate transferring KB articles from Pre to Prod. Configure Make.com to fetch articles from Pre instance then insert them into Prod. This avoids dependency on packages and works seamlessly across versions.

Thank you
Mohamed
 

Mohamed Ouederni,


Interesting, do you use this in other use cases ?

Damien

Show all comments
case
feedback
classicUI
Sales_Creatio_enterprise_edition
8.0

Hi guys! We have issue with CaseRatingFeedbackPage - in page we have just 2 radio button, 1 text area and 1 submit button. But page performance is so slow.


its how page looks:



 

Like 1

Like

8 comments
Best reply

and it loads a lot of js files:

and it loads a lot of js files:

Hello!

Thank you for sharing the details. Based on the provided information, here are a few key theories about what could be causing the performance issues on the CaseRatingFeedbackPage:
 

  1. Number of Requests:
    A high number of requests being triggered when the page loads or during user interaction can significantly impact performance. This could be related to customizations or additional scripts implemented on the page, which might introduce extra requests.
     
  2. Network Speed or Connection Issues:
    The fact that a small file (e.g., 33 KB) takes 2 seconds to load strongly indicates potential problems with the internet connection or network conditions. This delay could result from low bandwidth, high latency, or temporary connectivity issues.

    Recommended Next Steps:
     
  3. Analyze Requests and Customizations: Use a network monitoring tool (e.g., Chrome DevTools) to identify unnecessary or excessive requests. Pay particular attention to requests introduced by custom scripts or third-party dependencies.
     
  4. Check Network Conditions: Test the page performance under different network conditions to confirm if the issue persists with stable and high-speed internet.

    Best regards,
    Anton

Anton Starikov,

Hi Anton, thanks for response. There is no any network/speed issue. In the network I see a lot of JS loading which initiator is "error-list-dialog.js". 
here is the added code to this page:
 

Kamran Mammadov,

The fact that the files are taking so long to download indicates a network problem. Could you please check this also?
Is the result the same with other networks?

Anton Starikov,

Yes, it comes as issue from business, so it tested in different environments/networks

For what it's worth, the CaseRatingFeedbackPage always loads horribly slow for me as well, even without customization to it. Even for cases with Creatio in their success portal, often the page doesn't even completely load.

Ryan

Yep, 

A couple pages still needs some code optimization for performance. In general, load time is also very very sensitive to wifi quality I noticed, a whole much more than any other of our web apps we use.  

Lots of improvements happened last year, hopefully this trend of performance improvements will continue :). 

 

Thanks to all!

Show all comments
marketplace
map
Dashboard_widget
chart
dashboard
addon
Sales_Creatio_enterprise_edition
8.0

Hello! 

I'd like to ask for your advice please on how to use the Map widget for Creatio add-on. 
https://marketplace.creatio.com/app/map-widget-creatio

According to the add-on description it should appear in the chart dashboard type as 'Bubble map'. Please see the screenshot below. 

image.png

However, when I create a chart dashboard the 'Bubble map' is not there on the list. 



I have also checked the widget type and by default it's always like the one below, also on a new bundle. 


 

Could you please explain to me how can I built such bubble map dashboard?
I'd appreciate if you could share your expertise on this matter. 

Sales creatio, v. 8.1.4

Best Regards,
Jacek Harlejczyk

Like 1

Like

5 comments
Best reply

Jacek Harlejczyk,

 

Sorry for the delayed reply. The solution is now compatible with all Creatio products. Please install the updated version from the Marketplace and let me know if everything works as expected.

Have a good one!

Hi Jacek,

 

The "Bubble map" type is available for only the Map chart. We will add this note to the listing description.

Olena Sidko,

 

Hi Olena,

 

Thanks for getting back on this. 

 

The thing is that when I add a new dashboard, I cannot see this 'Map chart' dashboard type. Would you know what could be causing this? 

 

All the nest in 2025! :-)
Jacek 

Hello! Would anyone have any idea why the 'Map chart' dashboard type is not listed? Thanks!

 

Jacek Harlejczyk,

 

Sorry for the delayed reply. The solution is now compatible with all Creatio products. Please install the updated version from the Marketplace and let me know if everything works as expected.

Have a good one!

Olena Sidko,

Thank you for your help. It's working now. 
Best!
Jacek

Show all comments
products
objects
Hierarchy
brands
Models
Sales_Creatio_enterprise_edition
8.0

Hi Community, I'm trying to create a system, that allows me to easily assign Brands and Models to Products and spare parts, to make it easier for the support teams and sales team to find related products. For the "main" products i.e a laptop, this is easy enough, i.e Brand: Lenove, Model: Thinkpad 4

 

However, now that I'm looking at spare parts the same logic becomes much more difficult i.e a charging cable. The charging cable might be suitable for Lenove Laptops and Asus Laptops and multiple models of each. 

 

How do I assign multiple brands and models to that charger? The only options I see is to create merged brands and model i.e "Asus, Lenovo", however I am worried that this will get very messy very quickly and impossible to maintain as new products get added to the inventory... 

 

In the perfect world, I would like to be able to open any product and have a filtered list by (product brand and product model) on the same page, which will display all spare parts and accessories that is compatible with that product. 

 

Does anyone else face similar issues? Maybe I'm just overthinking it all and there is a really easy solution to it :)!

 

Thank you in advance!

 

Julia 

 

 

Like 0

Like

3 comments

Hello!

Thank you for the detailed description of the problem. The implementation you described assumes the use of a many-to-many relationship, which cannot be supported directly in the relational database structure.


Please note that in relational databases, the many-to-many relationship cannot be directly implemented because it violates the principles of the relational model, which is based on atomic data and normalization. Instead, such relationships are resolved using an intermediate (junction) table.

These are tables that reference two other tables and define the relationships between them. For instance, if we have Table 1 and Table 2, and we need to establish a multi-relationship between them (e.g., linking a record in Table 1 to multiple records in Table 2), we would create a junction table. This table would contain references to both tables and define the dependencies.

This approach allows us to implement a multi-selection mechanism, such as associating a product with multiple brands or categories (e.g., one product having three or more associated brands).

 

Here’s an example of how the table could look:

CompatibilityID    ProductID    BrandID
1                             101                1
2                             102                1

3                             101                2

Thank you Arsenii Ostapyk, that seems like it may be the solution to my problem. I have done a search through Creatio Academy for "junction" or "junction table". Can you point me in the right direction on where I can find information on how I go setting this up?

 

Julia Molnar,

 

Please note that we do not have any instructions or examples for this, since the question relates to the general Database structure principles, rather than to the Creatio system functionality. However, you are welcome to use the public open sources for more in-depth details on the subject.

Show all comments
FreedomUI
detail
Filters
Sales_Creatio_enterprise_edition
8.0

Hi Community,

 

We are trying to create a filter for this detail, that will use two conditions (one for each column) and a logical operator of “OR”. So basically, we only want the records that have the main record id on one of these columns (Contrato or Contrato Umbrella).

 

 

To achieve this, we first tried to add the filter using the FreedomUI Page Designer. However, the filter does not work with the logical operator “OR”.

 

 

So we needed to add it manually, through code. By following this post https://community.creatio.com/questions/detail-filter-freedom-ui. But that didn’t work.

 

 

An alternative was to add the filter in the viewModelConfigDiff section, but we don’t know how can we make the value dynamic.

 

 

Could you please help us find a solution to this problem?

 

Thank you.

Like 3

Like

1 comments

Hello Pedro,

Please review one of the community questions to find the example of Terrasoft.LogicalOperatorType.OR usage.

Additionally here is an explanation of how filtration on Detail work for FreedomUI. 

Case description:
On Contacts page there is a Job experience detail with listed companies where the person worked. Our goal is to show only those departments in the department field that are specified for chosen employer (Account object). So, for this case, Alpha Business has only 2 departments listed in the Departments detail. We only want to see those 2 departments when choosing a department for this account on Job experience detail on Contact page. 

For filtering we basically need just 2 base handlers to be triggered:

  1. crt.DataGridActivateRowBusinessRulesRequest – triggered when we click on an existing detail row or add a new one.
  2. crt.HandleViewModelAttributeChangeRequest – triggered when we change a value of fields.

We also need to create our own handler which we can name usr.ApplyDepartmentFilter. This one would find the currently active row of our detail to have access to its manipulations. After that, we check if account field is filled in and if yes, we create a filter for the Department field. To apply it, we need to use setValue method by targeting filterAttributeName that can be created using the formula: 
"{detailName}DS_{targetFieldName}_List_BusinessRule_Filter".
After that, it is important to use markAsPristine method to make sure that the attribute is applied silently, without forcing us to save the row.

As for crt.DataGridActivateRowBusinessRulesRequest, here we just need to filter it by request.dataGridViewElementName === "CareerList" to target only the detail needed and then call the execution of usr.ApplyDepartmentFilter request that was added earlier.

In crt.HandleViewModelAttributeChangeRequest handler we need to cover the situation when the Employer (Account) field is changed to update the filtration for Department field. First of all, we check if request.attributeName === "CareerList". After that we select the active row and get control over Account field. We check if it’s changed by using account?.dirty property and also if it has value with account?.value?.value, because we would want to filter Department field only in case the Employer is filled in. If those 2 conditions are met, we use markAsPristine method for the account field attribute. We use this one here because it will allow us to handle the subsequent changes of the Employer field. Without it, the field will remain dirty until we save the row. Eventually, we need to set value of the Department field to null using: row?.getAttributeControl(attributeName + "DS_Department").setValue(null, {silent: true});
After that, the usr.ApplyDepartmentFilter handler can be executed to apply the filtration of Department field by Employer.

Show all comments