Creating a LaborDtl from uBAQ

,

image

Custom Code he says. You’ll have more control.

It’s writing the custom code block… I have no clue.

Check this thread out,

Get started down that path and come back if you get stuck

Do you know what adapters I need to use?

I have added Labor and LaborDtl

image

no Adapters this is server side.

The link I gave you that points to my example is for Server Side (BPM) no adapters needed.

1 Like

No problem, one last question.

laborBO.DefaultOprSeq(ref lds,opSeq, out msg);

What is msg

Usually, I ignore that last msg part, or assign it to a string variable and then ignore it. Most of the time you don’t need it.

msg is a string variable that will come back with a message if the business objects determines there’s a warning or something special.

Most of the time you can ignore it, pass in a variable but don’t need to do anything with it.

foreach(var r in ttResults.Where(r => r.Updated()))
{

//Variables
 int defaultOpr = (r.JobOper_OprSeq); // Find Operation
 string defaultEmp = (r.Calculated_cEmployeeNum); //Find Employee Number (Epicor Super)
 DateTime clockDate = (BpmFunc.Today()); //Today's Date
 decimal clockHours = 7.5m; //Clock Hours e.g 7.5 hours.
 bool shopFloor = false;
 string msg = "";
 string expCode = "EXP";
 
 
      using(var laborBO = Ice.Assemblies.ServiceRenderer.GetService<LaborSvcContract>(Db))
      {
              LaborTableset lds = new LaborTableset();
              laborBO.GetNewLaborDtlNoHdr(ref lds, defaultEmp, shopFloor, clockDate, clockHours, clockDate, clockHours);
                lds.LaborDtl[0].LaborType = "P";
                lds.LaborDtl[0].LaborTypePseudo = "P";
                lds.LaborDtl[0].JobNum = r.Calculated_cOldestJob;
                lds.LaborDtl[0].LaborNote = r.Calculated_cLaborNote;
                lds.LaborDtl[0].ExpenseCode = expCode;
                lds.LaborDtl[0].LaborEntryMethod = "Q";
                laborBO.LaborRateCalc( ref lds);
                laborBO.DefaultOprSeq(ref lds,defaultOpr, out msg);
                laborBO.LaborRateCalc(ref lds);
                laborBO.CheckWarnings(ref lds,out msg);
               laborBO.Update(ref lds);
      }
}

Correct?

1 Like

Looks fine, give it a test and see

Any way to invoke Submit for Approval within the custom code? It’s working perfectly as well…

I have tried.

laborBO.SubmitForApproval(ref lds,false,out msg);

What does the trace say when you submit in the UI?

1 Like

image

foreach(var r in ttResults.Where(r => r.Updated()))
{

//Variables
 int defaultOpr = (r.JobOper_OprSeq); // Find Operation
 string defaultEmp = (r.Calculated_cEmployeeNum); //Find Employee Number (Epicor Super)
 DateTime clockDate = (BpmFunc.Today()); //Today's Date
 decimal clockHours = 7.5m; //Clock Hours e.g 7.5 hours.
 bool shopFloor = false;
 string msg = "";
 string expCode = "EXP";
 string defaultCompany = (callContextClient.CurrentCompany);
 string cMessageText = "";

 
      using(var laborBO = Ice.Assemblies.ServiceRenderer.GetService<LaborSvcContract>(Db))
      {
              LaborTableset lds = new LaborTableset();
              laborBO.GetNewLaborDtlNoHdr(ref lds, defaultEmp, shopFloor, clockDate, clockHours, clockDate, clockHours);
                lds.LaborDtl[0].Company = defaultCompany;
                lds.LaborDtl[0].LaborType = "P";
                lds.LaborDtl[0].LaborTypePseudo = "P";
                lds.LaborDtl[0].JobNum = r.Calculated_cOldestJob;
                lds.LaborDtl[0].LaborNote = r.Calculated_cLaborNote;
                lds.LaborDtl[0].ExpenseCode = expCode;
                lds.LaborDtl[0].LaborEntryMethod = "Q";
                lds.LaborDtl[0].LaborQty = r.Calculated_cAvailableToBook;
                lds.LaborDtl[0].RowMod = "U";
                laborBO.LaborRateCalc(ref lds);
                laborBO.DefaultOprSeq(ref lds,defaultOpr, out msg);
                laborBO.LaborRateCalc(ref lds);
                laborBO.CheckWarnings(ref lds,out msg);
               //laborBO.SubmitForApproval(ref lds,false,out msg);
                LaborDtlRow ld = lds.LaborDtl.Where(t => t.Added()).FirstOrDefault();
                laborBO.Update(ref lds);
                ld.RowMod = "U";
                laborBO.ValidateChargeRateForTimeType(ref lds, out msg);
                laborBO.SubmitForApproval(ref lds, false, out msg);
                }
                
}

Any ideas? I have followed the trace!

What does the Error Detail say? What do you see in the server event log?

Write your own trace logs so you can see where in your code it is failing

I have resolved it now. It was due to having an additional RowMod above another RowMod. Stupid me! Thanks for all of your help :smiley:

2 Likes

This has now been transferred to production but it’s coming up with

Server Side Error
Server Side Exception
EpicorServerException
	Description: BPM runtime caught an unexpected exception of 'NullReferenceException' type.
See more info in the Inner Exception section of Exception Details.
	Program: Erp.Services.BO.Labor.dll
	Method: LaborHedAfterGetNew1
	Line Number: 11373
	Column Number: 13
	Original Exception Type: NullReferenceException
	Server Trace Stack:    at Erp.Services.BO.LaborSvc.LaborHedAfterGetNew1(Boolean ShopFloor) in C:\_Releases\ERP\UD10.2.400.38\Source\Server\Services\BO\Labor\Labor.cs:line 11373
   at Erp.Services.BO.LaborSvc.GetNewLaborDtlNoHdr(LaborTableset& ds, String EmployeeNum, Boolean ShopFloor, Nullable`1 ClockInDate, Decimal ClockInTime, Nullable`1 ClockOutDate, Decimal ClockOutTime) in C:\_Releases\ERP\UD10.2.400.38\Source\Server\Services\BO\Labor\Labor.cs:line 8601
   at Erp.Services.BO.LaborSvcFacade.GetNewLaborDtlNoHdr(LaborTableset& ds, String EmployeeNum, Boolean ShopFloor, Nullable`1 ClockInDate, Decimal ClockInTime, Nullable`1 ClockOutDate, Decimal ClockOutTime) in C:\_Releases\ERP\UD10.2.400.38\Source\Server\Services\BO\Labor\LaborSvcFacade.cs:line 2242
   at Epicor.Customization.Bpm.Ubaq4F47D38A47C24AA488ED6A1232C32B23.UpdateBaseDirective_createLaborDtlCC_7531BDF2E53D46B4B277BCC26D0F5397.A001_CustomCodeAction()
   at Epicor.Customization.Bpm.Ubaq4F47D38A47C24AA488ED6A1232C32B23.UpdateBaseDirective_createLaborDtlCC_7531BDF2E53D46B4B277BCC26D0F5397.ExecuteCore()
   at Epicor.Customization.Bpm.DirectiveBase`3.Execute(TParam parameters) in C:\_Releases\ICE\ICE3.2.400.0\Source\Server\Internal\Lib\Epicor.Customization.Bpm\DirectiveBase.Generic.cs:line 146

Any reason why?

Here is the code

foreach(var r in ttResults.Where(r => r.Updated()))
{
//Variables
 int defaultOpr = (r.JobOper_OprSeq); // Find Operation
 string defaultEmp = (r.Calculated_cEmployeeNum); //Find Employee Number (Epicor Super)
 DateTime clockDate = (BpmFunc.Today()); //Today's Date
 decimal clockHours = 7.5m; //Clock Hours e.g 7.5 hours.
 bool shopFloor = false;
 string msg = "";
 string expCode = "EXP";
 string defaultCompany = (callContextClient.CurrentCompany);
 string cMessageText = "";

      using(var laborBO = Ice.Assemblies.ServiceRenderer.GetService<LaborSvcContract>(Db))
      {
          if (r.Calculated_cOldestJob == null)
            {
             var message ="There is no job number associated with this negative quantity. ";
               throw new Ice.Common.BusinessObjectException(
                  new Ice.Common.BusinessObjectMessage(message)
                      {
                       Type = Ice.Common.BusinessObjectMessageType.Error,
                      });
                      break;
            
            }
              LaborTableset lds = new LaborTableset();
              laborBO.GetNewLaborDtlNoHdr(ref lds, defaultEmp, shopFloor, clockDate, clockHours, clockDate, clockHours);
                lds.LaborDtl[0].Company = defaultCompany;
                lds.LaborDtl[0].LaborType = "P";
                lds.LaborDtl[0].LaborTypePseudo = "P";
                lds.LaborDtl[0].JobNum = r.Calculated_cOldestJob;
                lds.LaborDtl[0].LaborNote = r.Calculated_cLaborNote;
                lds.LaborDtl[0].ExpenseCode = expCode;
                lds.LaborDtl[0].LaborEntryMethod = "Q";
                lds.LaborDtl[0].LaborQty = r.Calculated_cEstimatedQty;
                laborBO.LaborRateCalc(ref lds);
                laborBO.DefaultOprSeq(ref lds,defaultOpr, out msg);
                laborBO.LaborRateCalc(ref lds);
                laborBO.CheckWarnings(ref lds,out msg);
               //laborBO.SubmitForApproval(ref lds,false,out msg);
                LaborDtlRow ld = lds.LaborDtl.Where(t => t.Added()).FirstOrDefault();
                ld["Processed_c"] = r.Calculated_cProcess;
                laborBO.Update(ref lds);
                
                ld.RowMod = "U";
                laborBO.ValidateChargeRateForTimeType(ref lds, out msg);
                laborBO.SubmitForApproval(ref lds, false, out msg);
                }
                  
             var messageTextBuilder = new System.Text.StringBuilder();
                        
                        messageTextBuilder.Append("Labour record has been created and approved! Please refresh the dataset to continue.. \r\n\r\nJob Num: ");
                        messageTextBuilder.AppendFieldQuery(
                            this.ttResults
                                .Where(u => u.Updated())
                                .Select(u => u.Calculated_cOldestJob));
                        messageTextBuilder.Append(" - Qty Booked: ");
                        messageTextBuilder.AppendFieldQuery(
                            this.ttResults
                                .Where(u => u.Updated())
                                .Select(u => u.Calculated_cEstimatedQty));
                        messageTextBuilder.Append(" - Operation: ");
                        messageTextBuilder.AppendFieldQuery(
                            this.ttResults
                                .Where(u => u.Updated())
                                .Select(u => u.JobOper_OprSeq));
                        messageTextBuilder.Append(" ");
                        
                        var messageText = messageTextBuilder.ToString();
                    
                        this.PublishInfoMessage(messageText, Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual, "TEAGLE/TEAGLE_ClearingNegativeKits", "Update");
                   
}

So it was working fine until you added the message stuff right? (that’s a hint). Try commenting that out and see if it works.

My bet is, since you are trying to select an updated record, but you already updated it. So now it’s just a regular row.

Both message boxes have been removed but I’m still getting this issue.

foreach(var r in ttResults.Where(r => r.Updated()))
{
//Variables
 int defaultOpr = (r.JobOper_OprSeq); // Find Operation
 string defaultEmp = (r.Calculated_cEmployeeNum); //Find Employee Number (Epicor Super)
 DateTime clockDate = (BpmFunc.Today()); //Today's Date
 decimal clockHours = 7.5m; //Clock Hours e.g 7.5 hours.
 bool shopFloor = false;
 string msg = "";
 string expCode = "EXP";
 string defaultCompany = (callContextClient.CurrentCompany);
 string cMessageText = "";

      using(var laborBO = Ice.Assemblies.ServiceRenderer.GetService<LaborSvcContract>(Db))
      {

              LaborTableset lds = new LaborTableset();
              laborBO.GetNewLaborDtlNoHdr(ref lds, defaultEmp, shopFloor, clockDate, clockHours, clockDate, clockHours);
                lds.LaborDtl[0].Company = defaultCompany;
                lds.LaborDtl[0].LaborType = "P";
                lds.LaborDtl[0].LaborTypePseudo = "P";
                lds.LaborDtl[0].JobNum = r.Calculated_cOldestJob;
                lds.LaborDtl[0].LaborNote = r.Calculated_cLaborNote;
                lds.LaborDtl[0].ExpenseCode = expCode;
                lds.LaborDtl[0].LaborEntryMethod = "Q";
                lds.LaborDtl[0].LaborQty = r.Calculated_cEstimatedQty;
                laborBO.LaborRateCalc(ref lds);
                laborBO.DefaultOprSeq(ref lds,defaultOpr, out msg);
                laborBO.LaborRateCalc(ref lds);
                laborBO.CheckWarnings(ref lds,out msg);
               //laborBO.SubmitForApproval(ref lds,false,out msg);
                LaborDtlRow ld = lds.LaborDtl.Where(t => t.Added()).FirstOrDefault();
                ld["Processed_c"] = r.Calculated_cProcess;
                laborBO.Update(ref lds);
                
                ld.RowMod = "U";
                laborBO.ValidateChargeRateForTimeType(ref lds, out msg);
                laborBO.SubmitForApproval(ref lds, false, out msg);
                }

}

Extremely weird, I added a try-catch in and it’s working.