Using Epicor Custom Functions to Update PartOpr and JobOper

I’m trying to update the tables PartOpr and JobOper here is the code I’ve come up with so far but it doesn’t like it. Could use some pointers in the right direction. I am trying to create an api can I can call. Thanks!

Getting this error…
System.Drawing.Bitmap CS0234 The type or namespace name ‘Contracts’ does not exist in the namespace ‘Erp’ (are you missing an assembly reference?)

try
{
    var partSvc = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.PartSvcContract>(session);
    var dsPartOpr = partSvc.GetByID(ipPartNumber);

    foreach (var row in dsPartOpr.PartOpr)
    {
        if (row.OprSeq == ipOprSeq && row.OpCode == ipOpCode && row.Company == Session.CompanyID)
        {
            row.EstUnitCost = ipNewEstUnitCost;
            row.VendorNum = ipNewVendorNum;
            row.PurPoint = ipNewPurPoint;
properties
        }
    }

    partSvc.Update(dsPartOpr);
}
catch (Exception e)
{
    opErrorMsg = $"Error updating PartOpr: {e.Message}";
}

try
{
    var jobSvc = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.JobEntrySvcContract>(session);
    var dsJobOper = jobSvc.GetByID(ipJobNum);

    foreach (var row in dsJobOper.JobOper)
    {
        if (row.OprSeq == ipOprSeq && row.OpCode == ipOpCode && row.Company == Session.CompanyID && !row.JobNum.StartsWith("MRP") && row.OpComplete == false)
        {
            row.EstUnitCost = ipNewEstUnitCost;
            row.VendorNum = ipNewVendorNum;
            row.PurPoint = ipNewPurPoint;
   properties
        }
    }

    jobSvc.Update(dsJobOper);
}
catch (Exception e)
{
    opErrorMsg = $"Error updating JobOper: {e.Message}";
}

John,

Did you add the assembly reference?
Likely you will need Part and Job Entry references.

1 Like

That doesn’t look like Function syntax. There’s also a few caveats with JobEntry specifically, at least if you don’t allow edits to engineered jobs.

This is from a function I wrote that uplifts the revision on a job. This snippet first unengineers the job, then runs the update of the now-editable record. Note the lambda (=>) syntax vs the using statement more common in BPM’s,

foreach (var job in jobs)
{
    try
    {
        //Placing the txScope here instead of at the function itself
        //means that failed updates only roll back the specifc job.
        //loop will continue on to the next item in the jobs list.
        using (var txScope = IceContext.CreateDefaultTransactionScope())
        {
            this.CallService<Erp.Contracts.JobEntrySvcContract>(svc =>
            {
                //populate JobEntryTableset
                var jets = new Erp.Tablesets.JobEntryTableset();
                var newRow = jets.JobHead.NewRow();
                BufferCopy.Copy(job.JobHead, newRow);
                jets.JobHead.Add(newRow);
                //unengineer job to enable editing.
                jets.JobHead[0].JobEngineered = false;
                jets.JobHead[0].RowMod = "U";
                svc.ChangeJobHeadJobEngineered(ref jets);
                svc.Update(ref jets);
                //Clear and all details
                svc.DeleteAll(jets.JobHead[0].SysRowID);
                //set new revision
                jets.JobHead[0].RevisionNum = job.NewestRev;
                jets.JobHead[0].RowMod = "U";
                svc.Update(ref jets);
                //Get details, obvs
                jets = svc.GetDetails(
                      job.JobHead.JobNum, //currJobNum
                      0, //currAsmSeq
                      "Method", //sourceFile
                      0, //sourceQuote
                      0, //sourceLine
                      "", //sourceJob
                      0, //sourceAsm
                      job.JobHead.PartNum, //sourcePart
                      job.NewestRev, //sourceRev
                      "", //sourceAltMethod 
                      false, //resequence 
                      true, //useMethodForParts
                      true, //getCostsFromInv 
                      false); //getCostsFromTemp
                //Release job
                jets.JobHead[0].JobEngineered = true;
                jets.JobHead[0].RowMod = "U";
                svc.ChangeJobHeadJobEngineered(ref jets);
                svc.Update(ref jets);
                jets = svc.JobScheduling(job.JobHead.JobNum, true, 0, 0, false);
                //If job was originally released, re-release it.
                if (job.JobHead.JobReleased = true)
                {
                    //Update is really anal about header changes.
                    //IT DOES NOT LIKE ANY CHILD ROWS
                    //So I create a new empty JETS and populate the header only.
                    //Copy of the thing I did above to kickstart all this.
                    var relJets = new Erp.Tablesets.JobEntryTableset();
                    var newRelRow = relJets.JobHead.NewRow();
                    BufferCopy.Copy(jets.JobHead[0], newRelRow);
                    relJets.JobHead.Add(newRelRow);
                    relJets.JobHead[0].JobReleased = true;
                    relJets.JobHead[0].RowMod = "U";
                    svc.ChangeJobHeadJobReleased(ref relJets);
                    svc.Update(ref relJets);
                }
                if (job.JobHead.TravelerLastPrinted != null)
                {
                    var newPrintedJobRow = printedJobs.JobHead.NewRow();
                    BufferCopy.Copy(job.JobHead, newPrintedJobRow);
                    printedJobs.JobHead.Add(newPrintedJobRow);
                }
            });
            txScope.Complete();
        }
    }
    catch (Exception e)
    { 
        ErrMsg += "Job " + job.JobHead.JobNum + ": " + e.Message;
    }
}

As for JobEntry:

Note that I’m creating a JobEntryTableset that only contains the JobHead record, and only the JobHead record in order to un-engineer the job. No assemblies, ops or material. JobEntry.Update barfs if your do otherwise.

After unengineering the job, I have to pull those details again (or in this case, it’s in another “job” TableSet declared outside the scope of this snippet). Then I modify them, and call svc.Update. Then I re-engineer and Update a third time.

If you want to re-schedule and re-release, that’s a fourth update() call. And for that one you have to use the “JobHead record only” trick from earlier.

As for PartOpr…you really shouldn’t be touching that directly at all. That should go through Engineering Workbench. Which means checking a revision out into the workbench, modifying it, then checking it back in. I’ve automated parts of that process, as part of a rev-control system, but never the whole thing.