What is the recommended way to handle calculated data?

6
When modeling a Mendix application, what is the recommended way, or best practice, to handle calculated data? For example, if I want to calculate the total price of an order based on the product prices and the number of products ordered, how would I model this in a Mendix application? Of course, I would like to display these data in a grid and be able to sort and search on these data.
asked
2 answers
16

You can use the objects 'Order', 'OrderLine' and 'Product'.

Use the following associations: Order 0 -> 1 OrderLine and Orderline 1 -> 0 Product

In a dataview of order, you can use a nested grid with order lines. You can add a product with attribute price to an order line. Based on the amount of products, you can trigger a microflow on change to calculate the total amount of an order line. On commit or after delete of an order line, you can trigger a micro flow which calculate the total price of an order.

The orders can be shown in a datagrid with search and sort functions.

To keep your data up to date highly depends on the case. In this case: When an order is placed, it's based on the product prices and amounts of that moment. When product prices change in the future, you do not want to change the total prices of previous orders and order lines.

If you want to change all your orders of the past after product price changes, you should trigger a microflow which set all the new prices of the order lines and total prices of the previous orders. However, this last option isn't really an option due to fixed agreements with customers in the past. Summarized, it highly depends on your particular case.

Note: @ Johan's answer:

The option to create a virtual attribute TotalPrice in the object Order isn't really an option due to fixed agreements with customers in the past. You do not want to calculate the price changes on previous orders. Virtual attribute can be used for other calculations like 'Age'. However, in case of orders, I would not use virtual attributes.

answered
3

You can use virtual attributes to represent calculated values in objects. Define a virtual attribute by opening the properties of a metaobject (context menu, or double click on metaobject) and edit or add an attribute. If you select a microflow in the atttibute property window the attribute will be calculated using this microflow everytime the object is retrieved.

However, virtual attributes are not saved in the database (i.e. they are virtual). While searching and sorting data is done in the database you can't search or sort on virtual attributes.

So, if you want to search an sort on your calculated value you need to create a 'normal' attribute and calculate the value for this attribute with custom events everytime a value used for the calculation changes.

Concluding, you have two options:

  • Create a virtual attribute TotalPrice in the object Order. Let it point to a microflow which retrieves all products associated to this Order and sums up all prices.
  • Create a normal attribute TotalPrice in the object Order. You can calculate the TotalPrice using events as described by Fedor in his answer.

You should include these considerations in your choice:

  • As said before you can't sort an search on virtual attributes.
  • Virtual attributes are always calculated when an object is retrieved. So if you load a datagrid with 20 objects the microflow defined as the virutal attribute will be executed 20 times. While data is more read than changed events are better for performance.
answered