Error In Function

I am, trying to have a function that has both IssueMaterial and the JobOper table. The goal is to say if the Op is complete, then do not issue. However, I am getting this error:

The type ‘JobOperRow’ exists in both ‘Erp.Contracts.BO.JobClosing, Version=10.2.700.0, Culture=neutral, PublicKeyToken=vvvvvv’ and ‘Erp.Contracts.BO.JobEntry, Version=10.2.700.0, Culture=neutral, PublicKeyToken=vxvd’

Easiest workaround is to break it into two functions and pass between.

Isn’t it two libraries? If I recall correctly one library per project so the problem remains (though maybe not )

This has been a problem forever, would be easily remediated if Epicor would allow specifying reference aliases…

1 Like

Maybe explain exactly what you are doing. Might be something else clever you can do.

It was a problem upgrading to 2023.1 for me. Had to create a different library for IssueReturn Functions from JobEntry Functions.

The goal is if the Op is complete, then do not issue. In this case, throw an error message.

Did you have to create one that stopped people from issuing material to a closed Op?

I know I have to start with the Issue Material BO, but having a hard time pinpointing the BO to call to check for the Op is complete or not.

No, I am actually issuing Lot tracked material through report quantity with my function.
I could in application studio add a function call before the IssueMaterial to validate if the operation is complete using JobOperSearch I beleive.

Why do you need that ?

You should only need:
Erp.Contracts.BO.JobClosing &

to do what you want to do in a function.

I’m not 100% following. What setup would you use?

Ok the reason I asked you what exactly you are doing, is because I don’t understand exactly what you are trying to do.

With what you are describing, the normal approach would be a BPM on
IssueMaterial.PerformMaterialMovement (I think), and you would do your check there and throw a flag.

With you talking about functions, it sounds like you are doing something custom and outside the norm.

So what (in detail) are you doing and why?


Gotcha. Here we go…

First, Yes, I am doing a BPM from IssueMaterial on PrePerformMaterialMovement.

I then set the condition for TranQty changes from any to another.

Here is where it gets a bit crazy. IssueMaterial doesn’t have Operation of any kind and I need to see if the Operation is complete or not. It is only the MtlSeq via JobMtl. So, I figured a Function, but that doesn’t really work.

So I tried if tranqty changes then invoke JobMtlSearch BO, as I can link that to IssueMaterial. Aft that I invoke JobOpSearch BO. That worked fine, as I set it to send me an email with all the info. works perfect.

Lastly, IU put in the final condition, JobOper.OpComplete if the changed row is equal to true. This is where it breaks. It just doesn’t work.

Hey Will!

What would be even better is a description like:

“Users are issuing material before a certain operation is complete” or whatever. What is the business problem? There may be a different way to do this then trying to fix the technical issues with this solution.

Hey Mark! Been a while since we last spoke!

I am just being asked to make it so that no one can issue material to an operation that is already complete. If the operation is complete already, do not pass go.

We have an issue with people still issuing material to a completed Operation and it is causing issues for us.

Can you show me what you have or explain exactly how you linked it?
I’m not understanding the relationships.

If I know what the relationships are, we could do this in 2 or 3 lines of code.


Here’s some pics…
Condition 1

Linked to JobMTL

Linked to JobOper

Linked to Condition 2

Linked to Error Message

@klincecum Any thoughts on this?

Sorry, I forgot.

And now I’m sick!

I’ll take a look when I get back to a pc.

I don’t really do widgets, but you could widgetify this more.

Put a pre-processing directive on Erp.BO.IssueReturn.PrePerformMaterialMovement.
Add a boolean variable, opComplete.

Add this custom code:

  opComplete = false;

    IssueReturnRow oldRow = ds.IssueReturn.Where(x => String.IsNullOrEmpty(x.RowMod)).FirstOrDefault();
    IssueReturnRow newRow = ds.IssueReturn.Where(x => !String.IsNullOrEmpty(x.RowMod)).FirstOrDefault();
    if(oldRow.TranQty != newRow.TranQty)
        JobMtl jobMtl = Db.JobMtl.Where(jm => jm.JobNum == newRow.ToJobNum && jm.AssemblySeq == newRow.ToAssemblySeq && jm.MtlSeq == newRow.ToJobSeq).FirstOrDefault();
        JobOper jobOper = Db.JobOper.Where(jo => jo.JobNum == jobMtl.JobNum && jo.AssemblySeq == jobMtl.AssemblySeq && jo.OprSeq == jobMtl.RelatedOperation).FirstOrDefault();

        opComplete = jobOper.OpComplete;

  catch (Exception ex)
      //Do what you do with errors..

Add a condition widget to check opComplete, and raise an exception with the widget.