Hi, any suggestions on how to make a bpm pause for 1 second?
The bpm auto approves a PO requisition mandatory action if certain conditions have been met, it is triggered just after the requisition has been dispatched to that action. The dispatch and approval actions each write a record to the table ReqLog, however the primary key for this table comprises:
ChangeTime is in seconds and since both of the two writes occur consecutively the system throws a duplicate primary key error.
My thoughts were to pause the approval bpm for one second with a custom code c# function, any suggestions how this could be coded? Or any other ideas how to overcome the problem, can the bpm piggy back onto some scheduled activity? I had thought of forcibly incrementing the field ReqLogType, but instinct tells me this could cause problems elsewhere.
Thanks and regards
neil
I have had related problems with some projects and never found a fully satisfactory answer. Whenever I have introduced a pause in a BPM, everything pauses in lockstep and the problem still occurs after the pause. So Iāll be interested to see if anyone does have a good solution to that.
Two strategies have usually got me around the issue:
Split your updates into two custom code blocks in the BPM and set the second one to run async. Often that gives just enough of a time gap (and solves the threading problem) that everything sorts out tidily.
Remove part of the routine out of the BPM and put it in Service Connect, either triggered from the BPM or by something the BPM does, and let it handle the things that need to happen later.
But as I say, Iāll be interested in anyone elseās take on the problem.
Hi @drbgrup
when you say āboth writing to the same tableā, is your BPM triggering the two actions on one method run or on two different methods? could you screen shot some details ? as per my understanding to Epicor logic and behaviour if two methods writing to the same table either this table must have a field to identify the source or one of them to āAddā the record and the other one to āUpdateā, thereby you can use the RowMod status and add it to your trigger conditions.
based on that, just thinking if you can move the validation to be pre-processing BPM and save all needed relevant key values to callcontextvariables with trigger flag, then invoke the approval method on your post-processing BPM if this flag is true and pass all your key values from the contextvariables and/or the rest from the tttable,
How about for your time key, on whichever the second one is, instead of current time, make it current time + 1 second (or 2 just for a safe gap). The record will be 1 second off real time, but that should get both of these records committed. As long as you are only running the BPM once every two seconds max.
The best answer would be to make one of the keys into a GUID so they never match. But Iām guessing you may be too far in the process to change it.
edit I was thinking this was writing to a UD table, so you canāt change the keys.
The first write is invoked normally in the (unmodified) Base Processing of the āUpdateā method of the business object Req, initiated by user action on the Requisition Entry form.
The second write is invoked in my Pre-BPM on the method āRDMenuFlagsā of the business object Req. I have hooked into this method for no other reason than it always follows the Update method.
I Have attached some screen grabs that illustrate in more detail the process flow, as far a I can see the problem is with the 2nd write occurring within the same second as the 1st write. If only the PK field ChangeTime was in milliseconds.
I say put a Data Directive on ReqLog table In-Transaction which checks to see if the keys already exist and if so, add 1 to ChangeTime. Putting a pause on a BPM is really really bad idea.
forgive my ignorance as our finance department do not use the financial module, so i have not done any work on this area, but reading through your tech. spec. document, and -correct me if i am wrong- you are trying to hook to a system flag method āRDMenuFlagsā and intercept it by passing parameters that already exist on the ###Base## run that is why you will end up having double records.
If i were you as i explained before just capture these key values in callcontextvariables with an extra true/false flag then find the actual method which runs when the requisitions get approved manually, invoke it and pass the relevant parameters to it in post-BPM on req-Update
Joseās suggestion works nicely and it feels ārightā with being implemented so to close the where the issue was occurring. Thanks again to everyone for your input. I hope to be able to give back one day.
Cheers
neil
@josecgomez did not work in my case, but I came up with an alternative that seems slightly better.
The issue I had with a Data Directive that added 1, was that it was still the same second, so it was still a duplicate. I tried checking for the duplicate first but it didnāt find one, not sure if I did something wrong or not. (it was Epicor 10.0). This was the Mass Part Number replace and some methods they had the same part on the method twiceā¦ No idea whyā¦ there were thousands of Methods.
I ended up setting ttPartAuditChangeTime =
ttPartAuditRow.ChangeTime + ((BpmFunc.Now().Millisecond)/100)
I didnāt want to add a thousand seconds but I wanted something with more precision.
Worked in my case.