BPM query

Hi guys, I have a question regarding RowMod. I have a post process BPM on the quote update. That does not work when I use RowMod == “U” but works when I comment out that line.
What I am doing is; I have a text box on the Header which contains a decimal between 1.2 and 3. This figure is used as a multiplier on the configured costs stored in QuoteDtl Number01 to give me a selling price. Sammples (SMP) are zero price and No Judgement Multiplier (NOJM) is at cost.
I also occasionally get the message that the line has been updated by another user and am wondering if I am doing something wrong.
Here is the code.

// Get the first "updated" row from  the dataset.
var ttQuoteHed_iterator = (from ttQuoteHed_Row in ttQuoteHed
                         //where (ttQuoteHed_Row.RowMod == "U")
                         select ttQuoteHed_Row).FirstOrDefault();

// Check if a row exists.
if (ttQuoteHed_iterator != null)
	{
		using (var txScope = Erp.ErpContext.CreateDefaultTransactionScope())
		{
    /* check if checkbox01 is true and judgement multiplier is present */
    bool cb1 = Convert.ToBoolean(ttQuoteHed_iterator["CheckBox01"]);
    decimal num1 = System.Convert.ToDecimal(ttQuoteHed_iterator["Number01"]);
   if (cb1 == true && num1 > 0)
   {
     decimal newprice = 0;
     foreach (var QuoteDtl in (from Row in Db.QuoteDtl
                where (Row.Company == Session.CompanyID &&
                      Row.QuoteNum == ttQuoteHed_iterator.QuoteNum &&
											Row.AnalysisCode != "NOJM")
                      select Row))
                {
                  newprice =  System.Convert.ToDecimal(QuoteDtl["Number01"]);
                  /* if number01 = 0 this is the first time we are updating this quote so store the price in number01 */
                  if (newprice == 0)
                  {
                    QuoteDtl["Number01"] = QuoteDtl.DocExpUnitPrice;
                    newprice = QuoteDtl.DocExpUnitPrice;
                  }
									if (QuoteDtl.AnalysisCode == "SMP")
									{
										newprice = 0;
									}
                  newprice = newprice * num1;
                  QuoteDtl.DocExpUnitPrice = newprice;
                  foreach (var QuoteQty in (from Row in Db.QuoteQty
                      where (Row.Company == Session.CompanyID &&
                      Row.QuoteNum == QuoteDtl.QuoteNum &&
                      Row.QuoteLine == QuoteDtl.QuoteLine)
                      select Row))
                      {
                        QuoteQty.DocUnitPrice = newprice;
                      }
      		       }
		Db.Validate();
		txScope.Complete();
    }
  } 

 }

Thanks

Adrian.

In general, the problem is that the BPM is post-processing. By then the row has already been updated, so the flags are gone.

It’s also not ideal to use the direct Db.Validate approach for standard fields in standard business objects, because you’re bypassing the logic contained in the objects. If you must, then adding a lock hint to the query will help with the “other user” message, but better to update using the BO if you possibly can.

1 Like

To add to Daryl comment, why aren’t you performing this in a pre-process. “before the update” must be the reason you are getting your messages “modified by another user”…

Also, I am sure such process could be acheived using widgets to modify table fields.

Pierre

Hi Daryl,
Thanks for the reply.
I did try putting this as a pre processing BPM but it errored constantly with the line has been updated by another user message.
So you think removing the Dbupdate, and putting it as a pre processing will work? I shall try it.
Thanks
Adrian.

Hi Pierre,
Widgets would be much easier I must admit. I thought about it, but would it update every line on a quote or just individual lines?
Regards
Adrian.

Bear in mind that in these BPMs you’re dealing with both temporary tables and database tables.

In pre-processing it’s easy to work with tt tables because they’re already in the process of being updated, so if you’re making changes to the same rows at the same time then it’s all quite logical. Working with totally unrelated database tables is also fine. Attempting to change database rows which are also in the temporary tables will be problematic.

So in your code you’re using rows returned from ttQuoteHed to try to update Db.QuoteDtl. That’s going to cause trouble wherever you do it. Change ttQuoteDtl instead, in pre-processing, and life should be a lot easier.

Thast is a good question. Never tested if all rows were available in the tt world… I beleive they are available…(reason why we use rowmod = U when dealing with them ? ) one way to check is in the widget make a change in the detail row see if the same change happened in all rows…

But I see your dilemma… I have the same with Sales Orders… I have a few UD fields to update on details line when a change occurs in releases, and vice versa. I use the Data directive on the table… all this because I used to get “changed by anoter user” error as well… I do this because I am editing UD fields only because I do not want to interfere with the “natural” way Epicor does updates…

For your purpose, changing a price field, would it work? You would have to verify the impact.

Another option would be to do a customization, on the field change of your iterator, change all your details lines prices…in code?.

Pierre