In the spirit of minimising code/making more of the config declarative rather than telling the system exactly how it should be doing things step by step, it would be very useful to be able to have calculated fields on entities in Creatio. Currently this needs to be done in business processes, which means creating the field in one place, creating the calculation somewhere else, and maintaining the conditions for firing of updates manually. It would be much better if we could have OOTB calculated fields much like many other CRM offerings on the market.

 

It would reduce issues around data not being updated at the right time, or changes in one place breaking config in others, and reduces processing time/disk IO spent on running business processes that have to read, modify and write data in addition to the data originally being written to disk - essentially duplicating the work the servers are having to do for each record. It can also centralise business logic into one place, rather than having different areas of code/config doing the calculation themselves and potentially becoming misaligned.

 

Ideally it would be able to incorporate data from other entities, including the ability to aggregate, but honestly just being able to have calculated fields based entirely on data on the same entity would be a big improvement.

1 comments

+1

Show all comments

Hi Team,



In the "Order" section there is a multicurrency field 'Total' and the values get auto-calculated/updated when a detail (OrderProduct) record is added/modified/deleted.



As this is a two different tables & modules, a sandbox should be used for the communication. Could you please assist us with the below queries?

1. EventHandler/Method name where the actual calculation is executed?

2. Where is the Sandbox mechanism used in OrderPageV2 & OrderProductDetailV2?

3. Which package has these client modules where the OOTB logic is written?

 

Attached the image reference,

 

 

Any insight on this would be appreciated.

 

 

BR,

Bhoobalan Palanivelu.

Like 0

Like

3 comments

Team,



Any insight on this?





Regards,

Bhoobalan Palanivelu.

One approach you can take is to add a subscriber to the detail. It is a function you can add to the detail definition to receive add/edit/delete updates from the detail. I believe that is possibly how it is working now out of the box. 

Locate the detail and add a subscriber like this: 

details: {
    ProductInProductsTab: {
        schemaName: "OrderProductDetailV2",
        entitySchemaName: "OrderProduct",
        filter: {
            masterColumn: "Id",
            detailColumn: "Order"
        },
        subscriber: { methodName: "refreshAmount" }
    }
}

Then add the function:

methods: {
  refreshAmount: function() {
    // refresh or do something since the detail has had something added/edited/deleted
  }
}

Ryan

Hi, 

This logic may be quite difficult to follow, and due to that I recommend you add breakpoints in the network to see it for yourself, but if you want a small step-by-step explanation then here it is:

When you are changing the product values the system triggers the method onBaseQuantityOrUnitChange in the schema BaseProductDetailPageV2? after it calcDiscountAmount, calcTaxAmount, and calcTotalAmount also start in this schema. Then the method saveRowChanges from the schema OrderProductDetailV2 and following the chain of methods we get to refreshAmount from BaseOrderPage and updateAmount/updateAmountFromDB from ProductEntryPageUtils. After that, triggers a modifyAmountESQ/updateAmountColumnValues from BaseOrderPage and in the end calls updateAmountColumnValues from ProductEntryPageUtils which is setting the "Amount" column.

I know I missed quite a lot of steps but it's really better to inspect this logic for yourself using breakpoints.

Show all comments

Im trying to create a calculated field to show a total of all records from a detail on a record, ive looked into using sql views, however I'm not sure if that would work as you cant filter by the record I don't think, are there any code solutions or anything similar?

Like 0

Like

1 comments

Hello,

 

You can try creating an integer column in the page (and in the object that this page represents) and create a business process that will change the value in this column once the record is added to the detail (or decrement once the value is removed). This way you can create the logic without additional code that will save resut in the server.

 

If you still want using the code - something similar is the functionality of the order product detail summary (that displays the number of products in order, can be found on the order page in the "products" tab). This logic can be found in the updateSummary method from the OrderProductDetailV2 from the Order package.

Show all comments

I'm looking to add a calculated field to a detail on a Section Edit page. I can find plenty of articles describing how calculated fields on section edit pages are implemented, but I'm not able to find any for a detail.

How I'm imagining this working is a trigger from the detail on load to calculate the column when the Edit Page is loaded. The column will be a object column, as I don't think virtual columns can be revealed in the column setup menu.

Has anyone been able to implement this functionality?

Like 0

Like

2 comments

Hi Morgan,



Indeed, there are no articles about calculated fields on a detail.



When a detail is created, there are two schemas created: detail schema and page schema. On the page schema of the detail you are able to work with attributes just like in the section. For example, you have a detail with editable list, you can create a calculated field logic (attribute with dependencies) on the detail page and logic will be working properly when you are modifying records in the detail grid.



If we are talking about your case, when you need to update some values based on a page field after detail is loaded, I think the best approach will be following:

1. Pass the value from the page to the detail. You can do that using sandbox messages or default values of the detail. Default values - is property that is passed from the page to the detail and is specified in defaultValues block. For example:

 

"UsrSchema7Detailff9f268f": {
	"schemaName": "UsrDetailSchema",
	"entitySchemaName": "usrDetailObject",
	"filter": {
		"detailColumn": "UsrMainObject",
		"masterColumn": "Id"
	},
	"defaultValues": {
		"SectionAttributeName": {
			"masterColumn": "DefaultValueName"
		}
	}
}

On the detail, you can handle both message and default value on the init function. DefaultValueName you will be able to get from this.get("DefaultValues") object. Once you get the value, set its value to some attribute.



2. Once you have the value that is used for calculations, you can override function prepareResponseCollection and use your value for calculations. This sample is on the community here.



Hope it helps!

Regards,

Dmytro

Thanks Dmytro, I'll try this method out

Show all comments

I am following the documentation about adding a calculated field you can find here.

I am following it piece by piece, and am doing everything exactly as it says but every time I try to view the calculated field in the edit orders page it says "Invalid column name UsrBalance". I've logged out and back in along with clearing cache. I also have recompiled it in the configuration advanced settings. When I download the package and import it though it works fine, no issues. I compare my package to their package and its the same. Maybe I am missing a part where I need to somehow validate the UsrBalance column or something I'm not sure. All parent inheritance is correct and followed as they have put it too.

Like 0

Like

1 comments

Please check if you have the value of system setting called "Prefix for object name" set as Usr and if it is not - you need to change it to Usr and relogin to the system and check the issue after that.

If it won't work, please try to find this column in the database and if it is not present in the database - please run update database structure for the object which is represented by the table where this column is present.

Also please double check if the field was added the same way to this part in the article:

define("OrderPageV2", [], function() {
    return {
        // Edit page object schema name.
        entitySchemaName: "Order",
        details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
        // The attributes property of the view model.
        attributes: {
            // Name of the view model attribute.
            "UsrBalance": {
                // Data type of the view model column.
                dataValueType: Terrasoft.DataValueType.FLOAT,
                // Array of configuration objects that determines [UsrBalance] column dependencies.
                dependencies: [
                    {
                        // The value in the [UsrBalance] column depends on the [Amount] 
                        // and [PaymentAmount] columns.
                        columns: ["Amount", "PaymentAmount"],
                        // Handler method, which is called on modifying the value of the on of the columns: [Amount] 
                        // and [PaymentAmount].
                        methodName: "calculateBalance"
                    }
                ]
            }
        },
        // Collection of the edit page view model methods.
        methods: {
            // Overriding the base Terrasoft.BasePageV2.onEntityInitialized method, which 
            // is triggerd after the edit page object schema has been initialized.
            onEntityInitialized: function() {
                // Method parent implementation is called.
                this.callParent(arguments);
                // Calling the handler method, which calculates the value in the [UsrBalance] column.
                this.calculateBalance();
            },
            // Handler method that calculates the value in the [UsrBalance] column.
            calculateBalance: function() {
                // Checking whether the [Amount] and [PaymentAmount] columns are initialized
                // when the edit page is opened. If not, then zero values are set for them.
                var amount = this.get("Amount");
                if (!amount) {
                    amount = 0;
                }
                var paymentAmount = this.get("PaymentAmount");
                if (!paymentAmount) {
                    paymentAmount = 0;
                }
                // Calculating the margin between the values in the [Amount] and [PaymentAmount] columns.
                var result = amount - paymentAmount;
                // The calculation result is set as the value in the [UsrBalance] column.
                this.set("UsrBalance", result);
            }
        },
        // Visual display of the [UsrBalance] column on the edit page.
        diff: /**SCHEMA_DIFF*/[
            {
                "operation": "insert",
                "parentName": "Header",
                "propertyName": "items",
                "name": "UsrBalance",
                "values": {
                    "bindTo": "UsrBalance",
                    "layout": {"column": 12, "row": 2, "colSpan": 12}
                }
            }
        ]/**SCHEMA_DIFF*/
    };
});
Show all comments

Hi,

Have two date fields for which I need to calculate the difference in days, i.e. UsrEndDate- UsrStartDate = UsrDayDifference

I have implemented the following code so far:

 

define("AccountPageV2", [], function() {

return {

entitySchemaName: "Account",

details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,

attributes: {

        "UsrDayDifference": {

               dataValueType: Terrasoft.DataValueType.FLOAT,

               dependencies: [

                   {

                       columns: ["UsrStartDate", "UsrEndDate"],

                       methodName: "calculateDays"

                   }

               ]

           }

},

 

 methods: {

            onEntityInitialized: function() {

                this.callParent(arguments);

                this.calculateDays();

            },

            calculateDays: function() {

                var result = (this.get("UsrEndDate") - this.get("UsrStartDate")).TotalDays;

                this.set("UsrDayDifference", result);

            }

        },

diff: /**SCHEMA_DIFF*/[

{

............

 

 

Can someone please explain what I'm doing wrong here?

 

 

Thank you,

 

Eduan

Like 0

Like

1 comments

p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px 'Helvetica Neue'; color: #454545}
span.Apple-tab-span {white-space:pre}

You can use this function: 

 

        numberOfDays: function(date1, date2) {

                if (date1 instanceof Date && date2 instanceof Date) {

                    var oneDay = 24 * 60 * 60 * 1000; // hours*minutes*seconds*milliseconds

                    var diffDays = Math.round(Math.abs((date1.getTime() - date2.getTime()) / oneDay));

                    return diffDays;

                }

                else {

                    return 0;

                }

            },

 

 

I hope it works for you.

Show all comments