Function Help - Update JobOper ProdStandard

Looking for some help here…
I am working on a function to adjust the ProdStandard value on a job operation.

The function takes 4 input parameters: JobNum, AssemblySeq, OprSeq, and Adjustment. (Where adjustment is the number of hours to increase/decrease the estimated hours on a job operation)

The function is purely code, using the CallService method to call the BO methods. I performed the desired steps in the UI and kept the Trace Log. The code attempts to replicate those same method calls.

CallService<Erp.Contracts.JobEntrySvcContract>(svc =>
{
    var jobData = svc.GetByID(JobNum);

    var jobOper = jobData.JobOper.FirstOrDefault(op => op.JobNum == JobNum && op.AssemblySeq == AssemblySeq && op.OprSeq == OprSeq);

    if (jobOper != null && Adjustment != 0)
    {
      var runQty = Math.Max(jobOper.RunQty, 1);
      var prodStandard = jobOper.ProdStandard;
      var stdFormat = jobOper.StdFormat;
      
      decimal newProdStandard = prodStandard;
      
      switch (stdFormat)
      {
        case "HR":
          newProdStandard = Math.Max(prodStandard + Adjustment, 0);
          break;
        
        case "HP":
          newProdStandard = Math.Max(prodStandard + (Adjustment / runQty), 0);
          break;
      }

      jobOper.ProdStandard = newProdStandard;
      jobOper.RowMod = "U";
      
      svc.ChangeJobOperProdStandard(ref jobData);
      svc.Update(ref jobData);
    }
});

When I attempt to run the function, I get the following error messages:

  • Cannot manually update the Production Labor Rate in JobOper.
  • Cannot manually update the Production Burden Rate in JobOper.
  • Cannot manually update the Setup Labor Rate in JobOper.
  • Cannot manually update the Setup Burden Rate in JobOper.

These are thrown by the JobOperBeforeUpdate method, which must be called internally as part of the JobEntry.Update.

I’m not making any change to those values, so I’m not sure what’s causing these errors to be thrown.

Any ideas?

When you call the Update method, the business objects are supposed to compare the “original” data to the updated data to see which fields have changed (for BPMs and such). Some business objects don’t automatically add this original row to the dataset when calling Update, and so you need to manually create a new data row, use BufferCopy to copy all data to it, and then add it to the dataset before calling update.

I use this code in a function to import a data file and update jobs’ scheduled resources. It uses the same concept but for JobOpDtl. This should be the same for JobOper in your case.

BufferCopyExample
// Change resource on job if resource doesn't match method's resource. Then release the job.
            CallService<Erp.Contracts.JobEntrySvcContract>(je => {
              var job = jobNum;
              var jobDS = je.GetByID(job);
              
              var jobOpDtl = jobDS.JobOpDtl.FirstOrDefault(op => op.OprSeq == 10 && !op.ResourceGrpID.ToUpper().Contains("TOOL"));
              // Make a copy of the row we're updating so that Epicor will actually update the records!
              var newJOD = (Erp.Tablesets.JobOpDtlRow) jobDS.JobOpDtl.NewRow();
              BufferCopy.Copy(jobOpDtl, newJOD);
              jobDS.JobOpDtl.Add(newJOD);
              
              jobOpDtl.RowMod = IceRow.ROWSTATE_UPDATED;
              
              je.ChangeJobOpDtlResourceID(jobResources[job], ref jobDS);
              
              //jobDS.JobOpDtl.FirstOrDefault(op => op.OprSeq == 10 && !op.ResourceGrpID.ToUpper().Contains("TOOL")).RowMod = IceRow.ROWSTATE_UPDATED;
              je.Update(ref jobDS);
              
              // Now release the job.
              jobDS = je.GetByID(job);
              
              var jobHead = jobDS.JobHead.FirstOrDefault();
              var newJobHead = (Erp.Tablesets.JobHeadRow) jobDS.JobHead.NewRow();
              BufferCopy.Copy(jobHead, newJobHead);
              jobDS.JobHead.Add(newJobHead);
              
              jobHead.JobReleased = true;
              jobHead.RowMod = IceRow.ROWSTATE_UPDATED;
              
              je.ChangeJobHeadJobReleased(ref jobDS);
              je.Update(ref jobDS);
              log.WriteLine($"    Changed resource and released job {job}.");
            });
4 Likes

That worked great, thank you Tyler!