MRP Suggestions for Unfirm Releases

Well… Epicor would recommend that you use Business Objects whenever possible, but I know (as an Epicor Employee) that there are many people who break this rule. When you do break the rule, you will have situations where you also break the data. Then it becomes your own responsibility to fix the data. If you make a BPM that updates the OrderRel, you need to make sure that it also updates any other fields.

1 Like

Agreed!

I have a feeling that what I’m asking must be very obvious to everyone but me, because so many people haven’t noticed / answered that part of my questions; but how do you “use the business object”!?

To take the above example specifically, if the non-canonical way is something like

OrderRel.FirmRelease = true;

in a piece of code; what is the corresponding business object way of accomplishing this? I have the guides referred to above, and I’ve looked through the code examples, but there must be some very obvious piece of the puzzle I’m missing!

OK, that’s very cool. Hopefully this will help me understand how to emulate what the application is doing, because right now that’s eluding me.Thanks very much.

Another tool you can use is the Business Logic Tester. You should be able to see it on your server under the Utilities folder. Once you set it up (use info in your Client/Config folder), you can open any Business Object and see all of the methods. You can also execute those methods right there as well. You’ll see the SalesOrder object has over 100 methods and a few of them will do what you want. Again, the hints are in the trace.

Keep at it!

One way to find out…

  1. go into an order
  2. go to the release, make sure it is NOT firm (save if necessary)
  3. TURN ON TRACING
  4. Check the FIRM box
  5. LOOK AT THE TRACE… you will probably find that there is a business object called when you check the box. If not, it is probably simply the SalesOrder.Update that does the update.

Method Directive, no?

Data directives are way easier and all-encompassing (my preference) [edit: see mea culpa further down], but it skips the BOs.

And with a method directive, you have to think of every way that a person might perform a task. Receipt and mass receipt. New part and duplicate part. Etc.

Not really. They give you access to the underlying table but they won’t keep your PartDtl in sync with your OrderRel. You’ll have to do that manually. Only the Method Directive will do that for you as Tim as noted.

Yes, and all the method directives I inherited simply have some condition and then some C# code that does something like

OrderRel.FirmRelease = true; 
Db.Validate();

I more or less understand tracing, and I’m not trying to figure out how to find the right BO.

I’m trying to figure out what people mean when they say to "use " it!

I can see that my BO needs to be SalesOrder, I guess:

image

But what does one do with it in order to “use the business object” as opposed to changing a database field? I feel like an idiot :neutral_face: but every time I ask “how do I use the BO”, somebody answers “How do I FIND the BO” instead!

Like I said, I must be asking something that’s so obvious to everyone else that my question doesn’t register.

I’m looking forward to suddenly realizing what you’ve all been saying, and I really appreciate the help!

So once you find the Business Object, now look at the Methods that are being called and the parameters going in and out.

Have you checked out the Trace Utility Tool yet? It will show you how to set up the trace and then process it.

I believe you’d need to emulate SalesOrder.Update in that case. You could do so with widgets by adding a couple “Invoke BO Method” widgets with a “Setter” widget.
image

To do so in code would be something like below. Note this is absolutely winged and no promise of accuracy or potential to work. Please google around to get real examples.

using (var soSvc = Ice.Assemblies.ServiceRenderer.GetService<SalesOrderSvcContract>(Db))
{
  int orderNum = 99999; 
  SalesOrderTableset ds = soSvc.GetByID(orderNum);
  foreach (OrderRelRow dr in ds.OrderRel)
  {
    dr.FirmRelease = true;
    dr.RowMod = "U";
  }
  
  soSvc.Update(ref ds);
}
1 Like

@Mark_Wonsil and @rosst thanks enormously. If I understand it then, allowing for syntactical changes which I’m sure I can find, I’m looking at something like:

basically

\\ using [this BO];
{
     \\ here are [some parameters];

     \\ create [this dataset] matching [parameters] from [BO]; 

      \\ foreach [thing] in [this dataset];
           {
                \\ change [these dataset fields];
           }
\\ call [this method] from [BO];
}

Is that basically what I’m trying to do? So instead of just getting the data from the dataset and then changing the Db.WhatEver directly and calling Db.Validate(), the “how” part I was missing is to access the dataset and change it before calling the BO method. As I suspected it seems obvious once it’s explained.

And I won’t ignore the widget methodology - I keep finding that the more I convince people to stick to built-in tools, the less problems we have.

Thank you both and @timshuwy, @Jason_Woods and @JasonMcD . I think I can keep moving forward now, having seen the puzzle pieces in trace, in the BL tool, in @josecgomez ’ cool visualizer and @rosst 's summing up.

2 Likes

Well, right, that was my point. Only method directives sync other tables. I know you all know that, but no one spelled it out, not even Tim, no offense.

As far as data directives being all-encompassing, I did word that badly. They address anything you want to address on that table itself, but not other tables. So they are easier, but often not better.

Data directives

  • Pros: (1) Don’t care what biz obj is doing it - there could be 3 or 4 or 20 that touch this table (PartTran). (2) It is easy to find the name of the table and field you are interested in
  • Cons: (1) Other things don’t get updated that should. (2) If you are a widget BPM-er (me), there are no widgets in the designer for invoking a BO.

Method directives

  • Pros: Uses system logic; has BO widgets; sometimes you can catch stuff way before the user is trying to save the record (like after entering a part number)
  • Cons: (1) Trying to figure out what on earth is the name of the object and method that will do what I want to do. (2) Realizing there are so many objects that do the same thing (line receipt and mass receipt, etc.; un-receiving is slightly different than re-receiving or a new receipt).
3 Likes

Yes, absolutely. You are spot on @JasonMcD. I was stuck in the context of this post but your post is perfect.

Thanks. And I edited the earlier post to address my bad wording. It sounds great in my head…

1 Like

So, I did a review of our system, and there are several major customized objects that firm or unfirm the release with a straight database setting and DB.Validate().

We have been struggling since go-live with inaccurate or downright ridiculous PO suggestions, and out of a few hundred of those, the PartDtl record is firm and the release is not on 160,with about 100 the other way around.

I’m absolutely floored - we’re a small company, and the impact is huge. Following and/or second - guessing suggestions has resulted in a 40% inflation in inventory over 18 months, as we fight the system and try to compensate for stockouts.

It seems likely this one thing is a major contributor, and several of those customizations were done by our integration partners.

1 Like

Thanks again @timshuwy and others. I have reviewed our customizations and there are way too many to dig into where OrderRel is directly manipulated (particularly OrderRel.FirmRelease in most cases). We have hundreds of examples of PartDtl.FirmRelease being true but OrderRel.FirmRelease being false.

If it is safe to run code to sync them up, would it be safe to create a task to run after MRP and sync them up every day? I hate the idea of a customization to fix the detritus of a customization, but there are a lot of them. I challenged our integration partner about them but they claim it’s not an issue and that Epicor processes should just clean up after the fact, which is obviously not happening.

the problem with waiting until AFTER MRP runs is that some things don’t process if there is not a firm release. MRP does not look at the order… it loos at PartDtl. So you could have a firm order, but MRP would not see it until the 2nd time you run it.
If you are going to do the datafix as a scheduled task, you should do it first.

1 Like