BPM Error Message


Guy’s i am working on a BPM to close jobs on the job receipt to inventory.

The BPM runs on the Erp.ReceiptsFromMfg.ReceiveMfgPartToInventory Pre and Post Method.
The Pre Method checks if all the ops are complete. Then go onto the Post Method.
The Post Method simply runs the code below.

The messages are just for debugging.
The first step is to get the QtyCompleted from the job.
The 2nd step is to check the PartTran Table for the QtyBooked to Stock.
The 3rd step is to check if the QtyBooked to Stock is equal to the QtyCompleted. If So then close the job.bpm error

Erp.Tables.JobHead jh;

var jn = callContextBpmData.ShortChar01;
var ptq = callContextBpmData.Number01;
var message = jn;
decimal jqc = 0;

this.PublishInfoMessage(message, Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual, "", "");

message = ptq.ToString();
this.PublishInfoMessage(message, Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual, "", "");

jh = (from JobHead_Row in Db.JobHead where JobHead_Row.Company == Session.CompanyID && JobHead_Row.JobNum == jn select JobHead_Row).FirstOrDefault();

     //Get the sum of booked parts
  decimal qc = (
    from pt in Db.PartTran.With(LockHint.NoLock)
    where pt.Company == Session.CompanyID &&
          pt.JobNum == jn &&
          pt.TranType == "MFG-STK"
    select pt.TranQty).Sum();
    message = qc.ToString();
    this.PublishInfoMessage(message, Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual, "", "");
    if (qc == jqc);
    using( var jcBO = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.JobClosingSvcContract>(Db))
        JobClosingTableset jcTS = new JobClosingTableset();
        //GetNewJobClosing Method
        jcBO.GetNewJobClosing(ref jcTS);
        //OnChangeJobNum Method
        string pcJobNum = jn;
        string pcMessage = "";
        jcBO.OnChangeJobNum(pcJobNum, ref jcTS, out pcMessage);
        //OnChangeJobClosed Method
        jcTS.JobClosing[0].JobClosed = true;
        jcTS.JobClosing[0].RowMod = "U";
        jcBO.OnChangeJobClosed(ref jcTS);
        //PreCloseJob Method
        bool RequiresUserInput = false;
        jcTS.JobClosing[0].JobClosed = true;
        jcTS.JobClosing[0].ClosedDate = DateTime.Today;
        jcTS.JobClosing[0].JobComplete = true;
        jcTS.JobClosing[0].JobCompletionDate = DateTime.Today;
        jcTS.JobClosing[0].QuantityContinue = 1;
        jcTS.JobClosing[0].WIPCleared = true;
        jcTS.JobClosing[0].RowMod = "U";
        jcBO.PreCloseJob(ref jcTS, out RequiresUserInput);
        //CloseJob Method
        jcBO.CloseJob(ref jcTS, out pcMessage);
      catch(Exception e){callContextBpmData.Character01 += e.ToString();}

Oof, that’s the notorious “type exists in both” bug… you can search this site for many examples.

Sometimes you can find clever ways around it, sometimes you are sh** out of luck.

I think @hkeric.wci is the expert on this, maybe you can pique his interest.

1 Like

You do not need code to auto close jobs. Have you tried Auto Complete and Auto Close Jobs under Job Management.

1 Like

There is no easy fix for that one. The only options that have worked for @josecgomez myself and others are:

  1. You need an External BPM to do that logic
  2. You need an Updatable BAQ which uses Advanced BPM to do that logic. Then your original BPM Calls the UBAQ. (Usually Pre EFX this is the way we have done it)
  3. You need an Epicor Function to do that logic
  4. You need to move the logic to another BPM that doesnt conflict with the same Table
  5. You need to move logic to the UI and simply do it on the front-end.
  6. Maybe you can Invoke UpdateExt pass through the dataset and maybe in the UpdateExt you can do that logic.
  7. Some people Use UD05.GetByID or GetList and hijack that BPM of a Table they dont use and invoke it.

Thanks Haso. for the feedback.

So if i was to set the bpmcontext.shortchar01 field to “Book To Stock” and then trap that condition under a separate BPM would that work ?

1 Like

I think most people probably just say screw the Business Objects and pull a Db.Validate() to update stuff directly.

Is this ever getting fixed?

I am not sure I know @Edge saw it in the past on the forums and I think Epicor’s answer was Epicor Functions. But I wouldn’t mind BPMs to be able to use alias just like Customizations do. I am not sure if @SAD has a trick up his sleeve. Besides the options I outlined above.

Sometimes when I am just moving my own fields MyField_c and I also would like to Default in an Epicor Field. I do the same, especially if its a harmless field but I always make sure to Reflect on Epicor’s code to understand what else I should be updating.

For example:

Take Project ID from POSugg and Default it into the PO.

Once I reflect on Epicors code They do a few checks and also bring in the ContractID, so it’s not always just as easy as Project ID :slight_smile:

I guess you have to make best judgement. Also after some major upgrades, sometimes review if Epicor added more checks/balances/defaults :slight_smile:

When it comes to something more complex like Closing a Job or Engineering a Job, or a Key Field (CustID, ShipTo, Etc…)… I try to stick to BO’s. Way too much logic to replicate.

It is mostly impossible. In general, assembly aliases were designed to solve conflicts with 3rd party libraries that cannot be changed in the scope of a consuming project.
I don’t plan to add such a thing to BPM. It is an overcomplicated and fragile approach.
Probably, aliases will be added to the EFx but it is not a short- or even midterm task.

So, AFAIU, moving part of logic to a function is the only solution available for now.

1 Like