Acrdding custom C# code to call the BP after the transaction is completed
Hello Community,
We are trying to trigger a business process as soon as a product has been added to an order. The filter for the BP to trigger requires the Order's Type and Order stage, as we have a conversion formula written based on the type of order as a condition. The default condition is to end the process. Unfortunately, whenever we add multiple products to an order, the process triggers but goes through the default condition. We noticed that the record gets created, but there is a delay in updating the values in the record. Before the values of the record are updated, the process is triggered, and as there is no order type in the DB, the process doesn't meet any of the conditions written. As a result, it takes the default value and ends the process.
To overcome this issue, we initially placed a timer after the process trigger before reading the products in the order. While it did work for the initial set of products added, the problem arose when multiple products (e.g., 20 products) were added to the order simultaneously. The updating of the DB takes time for all 20 records, and before that, the process would have triggered and waited for the timer to complete (5 seconds) and moved on to read the record. Consequently, some processes again went with the default flow.
As a workaround, we rearranged the timer in between reading the products in the order and reading the order itself. Additionally, we implemented a loop that goes back to the product in order if the order type is not filled in. This solution seems to work, but the looping takes more time when there are multiple processes running. As you know, in Creatio, the processes may be triggered in parallel, but the execution happens sequentially. This leads to more time being taken for the process to complete execution due to the delay in creating a record in the DB and updating the values in the created record.
We had reached out to support, and they had suggested that in the above case, there is no data to read in the record at the moment the "Read data" element is started. Consequently, the action will not result in further BP processing. They provided a link (Read uncommitted) and suggested adding a custom C# code, which can call the BP after the transaction is completed (by overriding virtual void UpdateAmountsByOrderId). This will call the base logic and afterward, it will call the process was their suggestion
Here are the steps for better clarity:
- A business process has been written for the conversion of the base price of the product based on the order type. The process is triggered when a product is added (Product in Order object), and the filter to trigger the process requires the Order Type and Order Stage to be filled in the Order object.
- The Order is created first, and later the product is added in the web app. However, in the mobile app, the Order and product are added at the same time.
- For example, if 20 products are added simultaneously, 20 processes are triggered, and they are executed in a FIFO way. Each process goes into a loop, leading to a subsequent delay in the execution of the process.
Question: As suggested by Creatio support, adding custom C# code to call the BP after the transaction is completed (i.e., when the record is created and values are updated), is there a sample code snippet available for the above scenario or an example snippet? Additionally, would like to know if this code snippet alone will work for both orders created from the web and mobile app, or if any code needs to be written in the mobile manifest to trigger the BP after the transaction is completed?
Regards,
Sivaranjani
Like
Hello,
The idea behind overriding a UpdateAmountsByOrderId is quite simple, you need to manually start your process after the base logic of the method is finished, for example:
public virtual void UpdateAmountsByOrderId(Guid orderId) { var productsEsq = new EntitySchemaQuery(UserConnection.EntitySchemaManager, "OrderProduct"); var idFilter = productsEsq.CreateFilterWithParameters(FilterComparisonType.Equal, "Order", orderId); productsEsq.Filters.Add(idFilter); var idColumn = productsEsq.AddColumn("Id"); var productEntities = productsEsq.GetEntityCollection(UserConnection); UpdateAmountsInfo orderProductInfo = null; decimal orderAmount, currencyPrimaryFactor = 0; ExecuteInTransaction(executor => { foreach (Entity productEntity in productEntities) { var orderProductId = productEntity.GetTypedColumnValue<Guid>(idColumn.Name); orderProductInfo = ProtectedUpdateAmounts(orderProductId, dbExecutor: executor); currencyPrimaryFactor = orderProductInfo.OrderProductToPrimaryFactor; } }); if (orderProductInfo == null) { var currencyInfo = GetOrderFinanceInfo(orderId); orderAmount = currencyInfo.Amount; currencyPrimaryFactor = GetToPrimaryFactor(currencyInfo.CurrencyInfo.Division, currencyInfo.CurrencyInfo.Rate); } else { orderAmount = orderProductInfo.OrderAmount; } UpdateSupplyPaymentElementsPercentageAndAmount(orderId, orderAmount, currencyPrimaryFactor); // Start the custom BP // UserConnection userConnection = Get<UserConnection>("UserConnection"); // IProcessEngine processEngine = userConnection.ProcessEngine; // IProcessExecutor processExecutor = processEngine.ProcessExecutor; // processExecutor.Execute("UsrTestProcess"); }
An example of how to start a BP can be found in this article.
This should work for both web a mobile since this logic triggers every time and so you don't need to change a mobile manifest.
Dmytro Vovchenko,
Thanks for the response.
Could you please specify when the method (UpdateAmountsByOrderId ) will be triggered and please confirm whether we need to overide this method in 'OrderProductDetailV2' schema.
If I'm not mistaken, it works every time you add a product.
You need to override the schema OrderAmountHelper, there is no need to touch OrderProductDetailV2
Dmytro Vovchenko,
Thanks for the response.
Could you please share any article on overriding Source code in Creatio?