Can DMT interact with and display debugging messages from BPM custom code?

Okay, editing because I realize that was a poorly worded question. If this was StackOverFlow you’d all be beating on me now.

I started with a question about data directives here: Are data directives triggered when DMT uploads? which resulted obliquely in me shifting to a method directive thanks to input fro @Jason_Woods . Big stuff for a new guy.

I now have code that does what I need on all manually-entered orders. It also works on a DMT order using “Sales Order Combined”, but the subsequent orders return “transaction aborted”.

Strangely, they do create their orders, but the evaluation step I coded does not occur.

To be clear, my question is:

Can I insert a debugging message that will return a message to the DMT error file and console, into the various steps of my code?

The code I’m using, which works manually, is below; comments on it are welcome too.

//MakeSetter 0.04 May 6, 2020 - Steve Fossey

using (var txScope = IceContext.CreateDefaultTransactionScope())
{
  var odtl = (from d in ttOrderDtl select d).FirstOrDefault();
  
  var orl = (from r in Db.OrderRel                              
        where   odtl.Company == r.Company &&                    
            odtl.OrderNum == r.OrderNum &&
            odtl.OrderLine == r.OrderLine &&
            r.Make 
        select r).FirstOrDefault();
        
  if (orl != null)
  {
    var ppl = (from pp in Db.PartPlant
          where  orl.Company == pp.Company &&
              orl.PartNum == pp.PartNum &&
              orl.Plant == pp.Plant &&
              pp.SourceType.Equals("M")
          select pp).FirstOrDefault();
          
    if (ppl != null)
    {
      foreach (var RelRow in (from r in Db.OrderRel.With(LockHint.UpdLock)
                  where  orl.Company == r.Company &&
                      orl.OrderNum == r.OrderNum &&
                      orl.OrderLine == r.OrderLine &&
                      orl.OrderRelNum == r.OrderRelNum &&
                      orl.PartNum == r.PartNum &&
                      orl.Plant == r.Plant &&
                      r.Make 
                  select r))
        {
          var pw = (from w in Db.PartWhse
                where   orl.Company == w.Company &&
                    orl.PartNum == w.PartNum &&
                    w.WarehouseCode.Contains(orl.Plant)
                select w).FirstOrDefault();
                
          if (orl.SellingReqQty <
              ( pw.OnHandQty -
                (  pw.SalesAllocatedQty +
                  pw.SalesDemandQty +
                  pw.ReservedQty +
                  pw.AllocatedQty)))
            {
              
              try
              {
                orl.Make = false;
                Db.Validate();
                txScope.Complete(); 
              }
              catch (Exception e)
              {
                this.PublishInfoMessage("parts on hand debug triggered with exception " + e, Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual,"","");
                
                txScope.Complete();
              }
            }              
        }   
    } 
  }
}

I also just learned how to format code in this forum, which works better than the code editor in Epicor :grin:

Hey, I just solved this meself!

I suppose all you elders are shaking your heads and smiling benignly, but this is pretty cool for me.

If I insert

 throw new Ice.Common.BusinessObjectException("triggered");

Into my code, I get a DMT debugging message thusly:

Good job! Now that you have working code…
I would recommend that you do not modify this field without using the Business Object. You will find that the Warehouse Demands are wrong and likely Time Phase. The Business Object updates a bunch of tables besides the OrderRel.

Yes, agreed - and where can I find info on calling the BO? I seem to be coming up blank. I assume I need to use the SalesOrder.Update that’s already running, and change its values? And I’m not finding a lot out there on this…

The nice thing is that you already have the standard dataset so you don’t need a new “ds” variable. It may be possible to skip step #3 also. If you can, it will save processing time.

  1. Use Pre-Processing in SalesOrder.Update to determine whether to enable Post-Processing.
  2. In Post-Processing, check if it’s been enabled by pre-processing
  3. Use SalesOrder.GetByID
  4. Change your value (you can use code here, but update the ttOrderRel table) and set RowMod = “U”
  5. Use SalesOrder.Update

OK, totally new guy question here - when you say “use SalesOrder.Update” what does that actually mean? I feel like a bit of an idiot for asking…

The thing is, I now have code that works, basically using

rel.make=false;
Db.Validate(rel);

and now that I know, roughly, what I’m looking at I find that the many expensive customizations we bought from our partner at go-live use that approach too. Aside from being familiar with lambdas where I have had to stick to linq-to-sql, I seem to have reinvented pretty much the same wheel they used.

So are you saying there’s something important missing? Is it as simple as literally adding

SalesOrder.Update();

to my code? Or am I completely off track here?

Also, I realize the above went off-topic for the original question. In the end, to avoid sending output to the DMT console in the form of an exception (thereby stopping the program) I learned from @davidbemenderfer about writing to to the server logs, which I implemented as

string b1 = "";
string b2 = "";

etc.

at the top of my code and then

b1 = "Release " + orl.OrderNum + " and source " + pp.SourceType;

(for example)

where I was trying to pull a message, and

Ice.Diagnostics.Log.WriteEntry("(1) " + b1 + " (2) " + b2 + " (3) " + b3;

to write to the log. It doesn’t show up in DMT but I can have the event viewer open in the server and refresh it.

I suppose this is basic but I felt clever leaving this in there for follow-up:

catch (Exception e)
{
Ice.Diagnostics.Log.WriteEntry("(1) " + b1 + " (2) " + " (3) " + b3 + " (except) " + e);
}

Hey, I’m learning :slight_smile:

You are doing a direct table update instead of using the same methods that Epicor performs. #1 mentions where to make the BPM (Method Directive on SalesOrder.Update, Pre-Processing). #3 & #5 is a BO Method call (a widget in Method Directives).

1 Like

OK, thanks - I see the widget, I’ll have to study it.