BPM to complete Job Operation

Hello,
I am writing a BPM to auto complete an operation on a job. I have found that I can write to the JobOper table within the BPM and set the OpComplete to true and QtyCompleted to the RunQty and the job shows that operation as green. Normally anything related to job operations are triggered via a labor entry (MES or time and expense) and then show up in the Labor tables. My question is, given our BPM does not create a labor entry and updates the JobOper table only, can anyone thing of anything that this may cause any issues down the road?

Thanks,
Tim

@tvonderhaar use caution with customization. Try to use backflushing to complete operations that you do not want people to report.

Look into backflush.

2 Likes

Yes! You should use the business objects not just writing to the fields directly.

4 Likes

Thank you for the replies. I will look into this more.

OK, I think the best approach for us is to us the BO.JobAdjustment.CommitLaborAdj rather than just marking the operations complete. Thank you both for the sanity check.

1 Like

Uncle! Iā€™m sorry up front for the stupid question, but Iā€™m struggling to figure out how to use the JobAdjustment BO. Iā€™m used to most other BOs that have a GetNew or something to prime the dataset. With JobAdjustment, I see a PreCommit and a CommitLaborAdj which would seem to me to need the dataset populated. Anyone have an example or hint they could share?

Tim

Did you ever get this BPM to work? Iā€™m searching for a way to have a job operation complete when a UD checkbox is checked.

1 Like

Yes I did. Been working well for years. Below is the code I usedā€¦with a few strings replaced with

References    : ERP.Contracts.BO.JobAdjustment

using Erp.Tablesets;
using Erp.Proxy.BO;
using Erp.Contracts;
using Erp.BO;

// Create Job Adjustment Tableset for Labor and connect to service contract
JobAdjustmentSvcContract lJobAdj = null;
JobAdjustmentTableset JobAdjDataSetLabor = new JobAdjustmentTableset();
lJobAdj = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.JobAdjustmentSvcContract>(Db);

// Populate Labor Detail record
JobAdjDataSetLabor.JALaborDtl.Add(new JALaborDtlRow());
JobAdjDataSetLabor.JALaborDtl[0].ClockInDate = DateTime.Now;
JobAdjDataSetLabor.JALaborDtl[0].LaborNote = "Auto Completed";
JobAdjDataSetLabor.JALaborDtl[0].AssemblySeq = 0;
JobAdjDataSetLabor.JALaborDtl[0].OprSeq = OSPrepOprSeq;
JobAdjDataSetLabor.JALaborDtl[0].QtyCompleted = 0;
JobAdjDataSetLabor.JALaborDtl[0].ActProdHours = 0;
JobAdjDataSetLabor.JALaborDtl[0].ActSetupHours = 0;
JobAdjDataSetLabor.JALaborDtl[0].ActBurCost = 0;
JobAdjDataSetLabor.JALaborDtl[0].ActLabCost = 0;
JobAdjDataSetLabor.JALaborDtl[0].EmployeeNum = <employeenum>;
JobAdjDataSetLabor.JALaborDtl[0].EmployeeName = <employeename>;

// Adjust quantities just in case there was an adjust made without op being completed
JobAdjDataSetLabor.JALaborDtl[0].LaborQty = t_JobOper_OSPrep.RunQty - t_JobOper_OSPrep.QtyCompleted;
JobAdjDataSetLabor.JALaborDtl[0].LaborType = "P";
JobAdjDataSetLabor.JALaborDtl[0].LaborHrs = 0;
JobAdjDataSetLabor.JALaborDtl[0].LaborCost = 0;
JobAdjDataSetLabor.JALaborDtl[0].BurdenHrs = 0;
JobAdjDataSetLabor.JALaborDtl[0].BurdenCost = 0;
JobAdjDataSetLabor.JALaborDtl[0].Complete = true;
JobAdjDataSetLabor.JALaborDtl[0].OpComplete = true;
JobAdjDataSetLabor.JALaborDtl[0].company = <company>;
JobAdjDataSetLabor.JALaborDtl[0].LaborHedSeq = 1;
JobAdjDataSetLabor.JALaborDtl[0].LaborDtlSeq = 1;
JobAdjDataSetLabor.JALaborDtl[0].OpCode = <operation>;
JobAdjDataSetLabor.JALaborDtl[0].ResourceGrpID = "";
JobAdjDataSetLabor.JALaborDtl[0].JcDept = <department>;
JobAdjDataSetLabor.JALaborDtl[0].JobNum = t_JobOper_OSPrep.JobNum.ToString();
JobAdjDataSetLabor.JALaborDtl[0].SysRowID = new Guid();
JobAdjDataSetLabor.JALaborDtl[0].RowMod = "A";		

// Commit Labor record
lJobAdj.CommitLaborAdj(ref JobAdjDataSetLabor);

2 Likes

Amazing - thank you!

Hi - I found this post and found it extremely helpful! Itā€™s in a slightly different context - when a Receipt Line is marked Received and the associated ā€œIssued Completeā€ checkbox for a Job subcontract is checked, we want to trigger a BPM to do a Subcontract adjustment forcing the operation to be marked complete.

I was able to get the Syntax to checkout, but I am getting a compiler error - any ideas on a workaround?

I have a Post Processing Method Directive on Erp.BO.Receipt.OnChangeDtlReceived.

Condition: The ttRcvDtl.IssuedComplete field of the changed row is equal to the true expression.

When true, set the following Variables:

MyJobNum: String ā€” Set to ttRcvDtlRow.JobNum

MyAssySeq: Integer ā€” Set to ttRcvDtlRow.AssemblySeq

MyOprSeq: Integer ā€” Set to ttRcvDtlRow.JobSeq

MyCompany: String ā€” Set to ttRcvHeadRow.Company

Then Execute the following Custom Code:

References: Erp.Contracts.BO.JobAdjustment

Usings:

using Erp.Tablesets;
using Erp.Proxy.BO;
using Erp.Contracts;
using Erp.BO;

Code:

// Create Job Adjustment Tableset for Labor and connect to service contract
JobAdjustmentTableset MyTs = new JobAdjustmentTableset();
var MyJobAdj =Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.JobAdjustmentSvcContract>(Db);

// Populate Labor Detail record
MyTs.JALaborDtl.Add(new JALaborDtlRow());
MyTs.JALaborDtl[0].ClockInDate = DateTime.Now;
MyTs.JALaborDtl[0].LaborNote = ā€œAuto Completedā€;
MyTs.JALaborDtl[0].AssemblySeq = MyAssySeq;
MyTs.JALaborDtl[0].OprSeq = MyOprSeq;
MyTs.JALaborDtl[0].QtyCompleted = 0;
MyTs.JALaborDtl[0].ActProdHours = 0;
MyTs.JALaborDtl[0].ActSetupHours = 0;
MyTs.JALaborDtl[0].ActBurCost = 0;
MyTs.JALaborDtl[0].ActLabCost = 0;
MyTs.JALaborDtl[0].EmployeeNum = string.Empty;
MyTs.JALaborDtl[0].EmployeeName = string.Empty;

MyTs.JALaborDtl[0].LaborQty = 0;
MyTs.JALaborDtl[0].LaborType = ā€œPā€;
MyTs.JALaborDtl[0].LaborHrs = 0;
MyTs.JALaborDtl[0].LaborCost = 0;
MyTs.JALaborDtl[0].BurdenHrs = 0;
MyTs.JALaborDtl[0].BurdenCost = 0;
MyTs.JALaborDtl[0].Complete = true;
MyTs.JALaborDtl[0].OpComplete = true;
MyTs.JALaborDtl[0].company = MyCompany;
MyTs.JALaborDtl[0].LaborHedSeq = 1;
MyTs.JALaborDtl[0].LaborDtlSeq = 1;
MyTs.JALaborDtl[0].OpCode = string.Empty;
MyTs.JALaborDtl[0].ResourceGrpID = string.Empty;
MyTs.JALaborDtl[0].JcDept = string.Empty;
MyTs.JALaborDtl[0].JobNum = MyJobNum;
MyTs.JALaborDtl[0].SysRowID = new Guid();
MyTs.JALaborDtl[0].RowMod = ā€œAā€;

string legalNumberMessage = string.Empty;

// Commit Labor record
MyJobAdj.CommitSubcontractAdj(ref MyTs, out legalNumberMessage);

Issue:

Using the Check Syntax button, this comes back as ok. But when I go to save the directive, I get the following error:

Error:

System Information

==================

AppServer Connection: https://SV-APP-01.projectsinc.local/EpicorTest
Form Name: Method Directives
Customization Name:
Menu ID: BPMN1200
Software Version: 3.2.700.0

============

Server Side Exception

There is at least one compilation error.
OnChangeDtlReceived.CommonTypes.cs(256,33): error CS0433: The type ā€˜LegalNumGenOptsTableā€™ exists in both ā€˜Erp.Contracts.BO.JobAdjustment, Version=10.2.700.0, Culture=neutral, PublicKeyToken=5d3fa3c7105d7992ā€™ and ā€˜Erp.Contracts.BO.Receipt, Version=10.2.700.0, Culture=neutral, PublicKeyToken=5d3fa3c7105d7992ā€™

Exception caught in: Epicor.ServiceModel

Error Detail

============

##!Correlation ID:##! 29f21457-8ddd-4245-b69a-920f44f96da0
##!Description:##! There is at least one compilation error.
##!Details:##!
OnChangeDtlReceived.CommonTypes.cs(256,33): error CS0433: The type ā€˜LegalNumGenOptsTableā€™ exists in both ā€˜Erp.Contracts.BO.JobAdjustment, Version=10.2.700.0, Culture=neutral, PublicKeyToken=5d3fa3c7105d7992ā€™ and ā€˜Erp.Contracts.BO.Receipt, Version=10.2.700.0, Culture=neutral, PublicKeyToken=5d3fa3c7105d7992ā€™
##!Program:##! Epicor.Customization.Core.dll
##!Method:##! Compile
##!Line Number:##! 78
##!Column Number:##! 13

Client Stack Trace

==================
at Epicor.ServiceModel.Channels.ImplBase`1.ShouldRethrowNonRetryableException(Exception ex, DataSet[] dataSets)
at Ice.Proxy.BO.BpMethodImpl.Update(BpMethodDataSet ds)
at Ice.Adapters.BpMethodAdapter.OnUpdate()
at Ice.Lib.Framework.EpiBaseAdapter.Update()
at Ice.UI.App.BpMethodEntry.Transactions.MainTransactionBase.adapterUpdate()

Is there a way to work around this error? I am having trouble.

Hello Harlan,
Best I can tell, your problem is not your code, but Epicorā€™s limitation that you cannot use the same dataset name twice. You are using table ā€˜LegalNumGenOptsTableā€™ which exists in both ā€˜Erp.Contracts.BO.JobAdjustment and Erp.Contracts.BO.Receipt. I ran into this problem trying to modify a newly created sales order from a quote. Seeing you are running 10.2.700, you have access to function calls which Iā€™ve read is a work around for this. Iā€™m running 10.2.300 so I had to do a less than optimal workaround and use a REST.