High level explanation of start activity on custom screen

Would anyone been willing to give a high level description of what it would take to make a custom screen to start and stop activity?

If I make queries and put them in grids, I should be able to map those values into the ttTable and run the BO that I find in the trace correct? I’ve never done it, but I would like to make a simplified version of the MES work queue that is tailored specifically to how we process our jobs so we can make clocking in and out of operation quicker and easier. I know that some of you have done such things.

I’m getting better at C# so these customizations don’t scare me as much as they used to. I don’t need all of the details, I can google that, but a push in the right direction would be greatly appreciated.



Just run a trace on start activity and basically what you want to do is create that dataset and instanciate the adapter for the given BO and call the methods.

Run a trace and give me the results I’ll give you some sample code for invoking that BO


1 Like

ok, I’m working on the trace. I figured it would be best to get the trace from the work queue since I want to be working with a grid in the final version of this. It’s annoying that once you open the work queue, the system doesn’t let you click any buttons on the trace so you can’t clear it right before you actually do what you want to do, so there is a bunch of extra get row stuff that I don’t think is relevant.

I tried just pasting in the trace, but it says that there are too many characters, so I just added the whole trace text file. There are a bunch of checks it runs through on the start before it makes the update. It looks like the end activity just runs a pretty simple update on the rows that were created in the start activity.

start and end trace.txt (329.4 KB)

1 Like

The work queue does a bunch of weirdo stuff I’d go with a straight up Start / End Activity… Grid or not you want the Core BO’s I’d think

1 Like

Alright, let me get that one.

To make a trace cleaner - shut down the system monitor by right clicking the icon in the system tray and choosing exit - That keeps the polling every 3 seconds or so from adding a lot of noise to the trace


OK, Here’s the start activity and end activity traces. Still a fair amount of stuff in each one. I’m working on getting my head around what all is being done.

And @bw2868bond, thanks for the tip about the system monitor. I forget about that one.

end activity.txt (29.6 KB)
Start activity.txt (291.8 KB)

So from what I can tell in the trace, every section like DefaultOprSeq etc, is updating the same dataset.

paramDataSet name=“ds” useDataSetNbr=“0”

So if I can populate the dataset for everything that is in the last one (update) That one should have everything that is needed for the update right?

Can I use some of the built in BO’s to get some of the information that each update section is getting? Or is it just better to build it into the query from the beginning? (like labor rate info, shift ID and that stuff)

You want to follow the trace to a T (for the most part)
So you want to make all those calls that they do, going straight to Update is generally a bad idea.
The first call to GetByID on LaborImpl() gets a hold of the current clocked in Labor record for the Employee and that returns the LaborDataSet which then is passed around to the other functions.
You would instanciate the Labor ADapter… like this and make the calls

var la = new LaborAdapter(oTrans);
la.GetByID(123456); //123456 being the current Labor Hed Sequence for the clocked in Employee (get it via BAQ, BOReader etc)
la.StartActivity(123456,"P"); //Start Production Activity
//..... etc... there are instances where you have to set the value of the data set and you can do it like this
la.LaborData.LaborDtl[0].Field="XX"; //Note that Index 0 is the first on the collection you'd have to find the right one would generally be la.LaborData.LaborDtl[la.LaborData.LaborDtl.Count-1]

Here is an example of creating a Labor record (Time & Expense like ) just to show you how do address fields, and how to set values and such. You’ll just mimic the same but with the right BO calls as outlined in the trace.

LaborAdapter la = new LaborAdapter(oTrans);
LaborDataSet lds;
la.GetNewLaborHed1("1",false, DateTime.Today);
la.DefaultOprSeq((int)drO["OprSeq"], out msg);
la.DefaultLaborQty(1, out msg);
la.CheckWarnings(out msg);
LaborDataSet.LaborDtlRow ld = (LaborDataSet.LaborDtlRow)lds.LaborDtl.Select("RowMod='A'")[0];
la.ValidateChargeRateForTimeType(out msg);
la.SubmitForApproval(false, out msg)

ok, so just working on wrapping my head around what’s happening, so tell me if this is correct.

The labor head sequence is created when the employee clocks in right? So they should have a current one that I can pull into the BAQ using calculated fields using context data correct? So I don’t have to create a labor head record, since they are already there. So the get by ID “la.GetByID(123456);” is simply pulling in the data set from the current labor head sequence for use later. So your code is creating a data set called la, which we can use later in the code. Is that a correct explanation?

For the second chunk of code, If I was doing this in MES, I wouldn’t call the GetNewLaborHed1 right? Since there will already be one for a clocked in employee? I would start with the get by ID for the labor head sequence. Then I would do a new labor detail to create a data set (same as the “ds” set in the trace right?) Could I then adjust that data set with all of the information needed? Gathering if from the header dataset we pulled in, and data from the grid? Then I would run that dataset through each of the BO’s in the trace to check for errors, and finally run last one, Update. Is that generally what’s happening?

On a details level, I’m missing the connection of what I see in the trace, to what I do in the code.

If I see this in the trace

Erp.Proxy.BO.LaborImpl DefaultJobNum

To call that in the code, does that go like this (we’ll assume la is my dataset)

la.DefaultJobNum(expression); (I will need to learn what I need to put in the expression…)

How does it know that Erp.Proxy.BO.LaborImpl is the BO being used? Is that assumed because of the LaborAdapter? Or am I supposed to call la.BOLaborImpl(); where you have La.BoConnect();

Sorry for my ignorance on this. The two different contexts are making it harder for me to see the patterns when I’m trying to see what is related to what.


Exactly! What goes in the expression are the parameters in the trace

LaborAdapter is an implementation of the LaborImpl. LaborAdapter instanciates and maintains the LaborImpl internally. That’s what the BOConnect() does.

Right the second chunk of code was just an example , GetNewLaborHed1 creates a new LaborHed which you already have since you are clocked in.


That makes sense. Just for general knowledge, do can I know what BO cross references to what adapter? Is it basically just replace Impl with Adapter? Or is it more complicated than that?

Do most of the things in the dataset get handled by the BO’s? For example, clock in times, clock out times, labor rate calculations, etc. When I run the appropriate BO, it should adjust the necessary fields right? I need to get enough information to create rows on start activity, (like JobNum, AssembleSeq, Opr, and various employee info etc. The stuff that you have to input on the start activity screens), and on end activity get labor quantity data, but a large majority of the items in the data set will be modified by the BO without me having to specifically code for it right? There are 243 columns in the data set, I would hate to have to control them all.

Yes the large majority of fields happen because of the “EpiMagic” in the BO’s


So when I am reading the data sets in the trace, it looks like the set that is shown after the BO is the state of the data set before the BO makes any changes right? So basically (I know this is probably stupid basic, buyt I’m just learning this) Whatever shows up in the parameters section of the BO are what I need to put in the expression part of the BO call. (like was mentioned earlier in the conversation, but I didn’t make that connection until now). So for the DefaultOprSeq call, there would be 3-1 parameters, so I need 2 arguments in the code. (it looks like “CallContext” is left out?)

la.DefaultOprSeq([“OprSeq”], out msg);

This would set my operation code in the data set, right?

So I wouldn’t actually manipulate the data set directly, I would call the BO to make the adjustments and pass along the required parameters. Right?

This is starting to make a lot more sense now.

Right that’s becasue the data you see is BEFORE the method call

1 Like

So this is what I would use to call the method, correct?

1 Like


1 Like

So once I get the method calls and parameters all set up, If I were to do this with info from a grid, I would just put that in a loop to go through the grid with an “if selected” and process each one through all of the method calls, right? Set the parameters as variables from the applicable row at the beginning of the loop, process the record, then repeat for all selected rows?

I’m parsing through the trace, and there is >LaborRateCalc< in there twice, with the same parameters. Do I need to run that twice? Do I just need to follow the trace and stop asking questions? Lol.