Kinetic Application Studio Best Practices for conditional complex logic

Here’s my original post (which may have been too high-level to describe the problem fully).

I’m starting over, because I believe I had started with the wrong approach.

Here’s what I’m trying; I’ll give more details than in the last post.

In our company, we use multiple production lines (Line A,B,C,D). Line D is for large jobs with fewer stations and fewer operations (with longer ProdStandard times).

As an aside, the “Line” value is stored in a JobHead UD field (sadly, we use Character01, but it is what it is).

In Job Entry, when a user attempts to change the Line, we would like to do the following:

  1. Data validation: Ensure new value for Line is allowed for this job type. That logic is somewhat complex (it depends on the PartNum of the job and a few other attributes).

  2. If it passes validation, we need to loop through the Job Operations, and change the LaborEntryMethod values (sometimes B, sometimes Q). We also need to loop through the JobOpDtl records, and change ResourceGrpID, ResourceID, and ProdStandard values (this also has complex logic).

So, I’m looking for the best practices to accomplish those tasks. If you look at the previous post, I initially tried to add an Event for After the Line field changed, and call a subroutine to make the updates. The problem with the approach is that it updated the database, but not the display buffer. So, modified fields in the buffer had not yet been written to the database, and the JobOper and JobOpDtl records had been updated (behind-the-scenes), but aren’t reflected in the UI.

I hope I am making sense here. Feel free to ask more questions, if it’s not clear.

This is easy enough to work around. In the UI, I would call an event when they change the line to make sure it’s allowed. The event would invoke an Epicor Function that would validate what they are doing, and return true or false. If it returns true, no issue. If it returns false, throw an info message and revert the “Line” value back to what it was originally. You could also do this in a pre-proc BPM, which might be a better option.

If you do the event in App-Studio to validate and it returns true, you can call another function in the event to update JobOper and JobOpDtl. Then after the function runs (on success), just call a refresh UI. That should get the UI to update the changes.

If you do it in a pre-proc BPM, you can then enable a post-proc BPM. In the post-proc, invoke the same function. If you do an event in app-studio “After Update” and have it refresh the UI, that should also reflect the background changes that happen in the post-proc BPM.

1 Like

I tried that. But doing a Refresh refreshes not only JobOper and JobOpDtl (which is what I want), but it also refreshes JobHead from the database. But JobHead had change(s) in the input buffer (such as the JobHead UD Character01 that we use for Line, and possibly other changes) that get overwritten from a Refresh.

That’s easy enough. Make your event look like this:

  1. DataTable - ColumnChanged: JobHead.Character01
  2. KineticFunction: ValidateLineChange
  3. Condition: {actionResult.LineChangeIsValid}
  4. Condition is false:
    4a. Throw Info Message that they can’t pick that line
    4b. After info message: row-update JobHead.Character01 to original value
  5. Condition is true:
    5a. Call Update (save all dirty values)
    5b. KineticFunction: UpdateJobOpersAndOpDtls
  6. RefreshUI

First, thank you (again) for taking the time to share with me.

I will see if I can do what you described. It seems right to me.

I’ll reply here when I have given it a go.

Thank you!

2 Likes

Kevins are best.

3 Likes

I have something similar on CustShipEntry. It’s not as involved. Basically a button that makes an API Call out to a carrier service to get the costs. It calls Update (saves any dirty values), make API call, returns the values > If there is a customer cost, call another function to add a ShipMisc line > Refresh the UI.

1 Like

You’re right on the Mark there.

5 Likes

I’ve also faced buffer vs database sync issues in Kinetic—updating the UI buffer first, then committing changes, made my logic much more reliable. Modular validation routines (based on job or PartNum) help keep things manageable during multi-record updates. Anyone else found good ways to batch these in Application Studio?

Should I use the Data Table event ColumnChanged (after the change)? Or the event ColumnChanging (before it changed)? If I use ColumnChanging, how do I access the value that it is changing to? And if I use ColumnChanged, how do I access the value that it changed from? Do I read it from the DB (which I can do)?

Should I return “OldLine” as a Return Param from ValidateLineChange, so that I know what the JobHead.Character01 value should be reset to if it failed validation?

You could set a separate event on ColumnChanging, and do a row-update to set TransView.OldLine or something to the original value, and then use ColumnChanged and do the event as described. Use row-update to revert the value to TransView.OldLine.

OR you could just use ColumnChanged and have the Epicor Function return the DB value as a response parameter.

Just to follow-up here. I’ve not had the time to work through the issues until recently, but now it’s all working!

So again, I want to thank everyone (especially the Kevin’s) for the help!

This is what I ended up with:

I used ColumnChanging trigger instead of ColumnChanged, for a number of reasons. I had started with ColumnChanged (out of ignorance), but when I reset the column at the end, it fired off another ColumnChanged event, which made me queasy that I could end up in the dreaded infinite loop, which could cause a black hole and civilization to collapse upon itself.

I named my event KCC_ColumnChanging_JobHead_Character01, triggered by the “changing” of that field.

  1. It calls the ValidateLine function, which returns ValidLineChange as a boolean. (This function also pops up the error message if it is invalid, so there is nothing left to be done after the routine if it failed validation.)
  2. The condition checks ValidLineChange:
  3. If false, we use the event-next event-cancel event (no need to reset the value).
  4. If true, we first write the buffer values to the db with SysUpdate.
  5. Then we call the UpdateLine function that does the magic of updating the JobHead, JobOper and JobOpDtl tables in response to the line change.
  6. Finally, we call the RefreshUI event to reload the buffer with the new db values.

Whew! It all works, and it only took me a few hundred iterations to get all my ducks in a row.

Once again, thank you to everyone. I really appreciate the help. I wanted to document the completed solution in hopes it may help someone else down the road.

3 Likes

Thanks for sharing.

FWIW, In case you do want to compare old and new values in your events client-side, use these expressions which eval in actions within the column change event context.

2 Likes