BPM Variable Help

Hello everyone

Anyone able to write this code? I want to be able to use null-coalescing but I can’t seem to figure it out!

Here is the code

foreach(var r in ttResults.Where(r => r.Updated()))
  {
  //Variables
   int defaultOpr = (r.JobOper_OprSeq); // Find Operation
   string defaultEmp = "99999" ; //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 = "";
   decimal overQty = (r.JobOper_OverrideQty_c);
   decimal compQty = (r.JobOper_QtyCompleted);
   decimal estQty = (r.Calculated_cEstimatedQty);
   decimal laborQty = estQty ?? new compQty ?? new overQty;
   decimal runQty = (r.JobOper_RunQty);
   decimal cHours = (r.Calculated_cEstLabourHours);
   string labourNote = "Auto Clearing Dirty Jobs";
   
      try
      {
        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.JobOper_JobNum;
                  lds.LaborDtl[0].LaborNote = labourNote;
                  lds.LaborDtl[0].ExpenseCode = expCode;
                  lds.LaborDtl[0].LaborEntryMethod = "Q";
                  lds.LaborDtl[0].LaborQty = laborQty;
                  lds.LaborDtl[0].LaborHrs = cHours;
                  lds.LaborDtl[0].BurdenHrs = cHours;
                  lds.LaborDtl[0].ClockInDate = clockDate;
                  lds.LaborDtl[0].ExpenseCode = expCode;
                  lds.LaborDtl[0].DspClockInTime = "07:30";
                  lds.LaborDtl[0].DspClockOutTime = "16:00";
                  lds.LaborDtl[0].ClockinTime = 7.50M;
                  lds.LaborDtl[0].ClockOutTime = 16.00M;
                  lds.LaborDtl[0].ActiveTrans = false;
                  lds.LaborDtl[0].LaborCollection = false;
                  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);
                    Db.Validate();
          }
      }
      catch (Exception ex)
      {
          Ice.Diagnostics.Log.WriteEntry($"EmpID = {defaultEmp}, JobNum = {r.JobOper_JobNum}, Opr = {defaultOpr} Qty = {laborQty} Labour Hours = {cHours} --Error: {ex.Message}", "Dirty Jobs");
      }
 }

There is one section but I’m getting errors.

decimal laborQty = estQty ?? new compQty ?? new overQty;

image

The calculation I’m trying to achieve is

If estQty is null then use compQty and if overQty is not null use that over priority)

remove the word new

new is for instantiating a new object.

Also decimals are not nullable you’d need Decimal for that to work me thinks.

What do you mean you need Decimal? How would be written?

Decimal (capital D) is an object (nullable)
decimal (lower case) is a primitive and not nullable (by standard means)

1 Like
   Decimal compQty = (r.JobOper_QtyCompleted); //BAQ Data
   Decimal estQty = (r.Calculated_cEstimatedQty); //BAQ Data
   Decimal estQty = (r.JobOper_OverrideQty_c); //BAQ Data
   Decimal laborQty = estQty ?? compQty ?? overQty;

Still gives me

CS0019	Operator '??' cannot be applied to operands of type 'decimal' and 'decimal'

I didn’t realise there was two different.

Decimals are not likely to be null (ever) don’t use null coalesce for these. Just check if they are zero. The only way those would be null is if your BAQ has a left join from Oper and there is no operation.

1 Like

No problem makes a little sense now!

How would you create an over-ride field though? There will be always some sort of value in either one of the two other fields but if a value is added to overQty that would be used. I just don’t know how to write that :smiley:

 Decimal laborQty = overQty>0?overQty:compQty>0?compQty:estQty;
4 Likes

Hi Jose,

I have a question. We have a field OverrideQty_c on JobOper but the uBAQ custom code is triggered by a boolean (process_c) changing to true but I need to recalculate a calculated field on the BAQ before creating the LaborDtl record.

How would you go about doing that? e.g If someone typed 4 in the updateable field in the uBAQ and ticked process the calculated field would remain 0 as it didn’t have the value of OverrideQty from JobOper as the value was only stored in the ttResults of the uBAQ.

I thought about having a condition if OverrideQty is greater than zero and process_c is true then update JobOper table with the value of OverrideQty from the BAQ and inform the user to refresh and rerun the uBAQ but there must be a better way than that.

@aarong The r.JobOper_OverrideQty_c in the update would hold the value that was typed in the baq, not the original value from JobOper.

1 Like

Thank you

The calculated field will need to written in custom code to allow it to capture the value from the updated field

Anyone able to help me write this calculated field in c# for a BPM

Field Name: cEstLabourHours

(CASE 
WHEN JobOper.SetupOpr_c = 1 AND JobOper.QtyCompleted = 1 THEN 0
WHEN JobOper.SetupOpr_c = 1 AND JobOper.OverrideQty_c > 0 THEN JobOper.OverrideQty_c * JobOper.EstSetHours
WHEN JobOper.SetupOpr_c = 0 THEN JobOper.ProdStandard * (JobOper.RunQty - JobOper.QtyCompleted) / 60 ELSE 0.00
END)
foreach(var r in ttResults.Where(r => r.Updated()))
  {
  //Variables
   int defaultOpr = (r.JobOper_OprSeq); // Set Operation from BAQ
   string defaultEmp = "99999" ; //Hard Coded (Emp Name: 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"; //Hard Coded
   string defaultCompany = (callContextClient.CurrentCompany);
   string cMessageText = "";
   decimal setHours = (r.JobOper_EstSetHours);
   decimal prodHours = (r.JobOper_ProdStandard);
   int runQty = (r.JobOper_RunQty);
   Decimal compQty = (r.JobOper_QtyCompleted); //BAQ Data
   Decimal estQty = (r.Calculated_cEstimatedQty); //BAQ Data
   Decimal overQty = (r.JobOper_OverrideQty_c);
   bool setupOpr = (r.JobOper_SetupOpr_c);
   Decimal laborQty = overQty>0?overQty:compQty>0?compQty:estQty;
   decimal runQty = (r.JobOper_RunQty); //BAQ Data
   decimal cHours = (r.Calculated_cEstLabourHours); //BAQ Data
   string labourNote = "Auto Clearing Dirty Jobs"; //Hard Coded
   
      try
      {
        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.JobOper_JobNum;
                  lds.LaborDtl[0].LaborNote = labourNote;
                  lds.LaborDtl[0].ExpenseCode = expCode;
                  lds.LaborDtl[0].LaborEntryMethod = "Q";
                  lds.LaborDtl[0].LaborQty = laborQty;
                  lds.LaborDtl[0].LaborHrs = cHours;
                  lds.LaborDtl[0].BurdenHrs = cHours;
                  lds.LaborDtl[0].ClockInDate = clockDate;
                  lds.LaborDtl[0].ExpenseCode = expCode;
                  lds.LaborDtl[0].DspClockInTime = "07:30";
                  lds.LaborDtl[0].DspClockOutTime = "16:00";
                  lds.LaborDtl[0].ClockinTime = 7.50M;
                  lds.LaborDtl[0].ClockOutTime = 16.00M;
                  lds.LaborDtl[0].ActiveTrans = false;
                  lds.LaborDtl[0].LaborCollection = false;
                  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);
                    Db.Validate();
          }
      }
      catch (Exception ex)
      {
          Ice.Diagnostics.Log.WriteEntry($"EmpID = {defaultEmp}, JobNum = {r.JobOper_JobNum}, Opr = {defaultOpr} Qty = {laborQty} Labour Hours = {cHours} --Error: {ex.Message}", "Dirty Jobs"); //Write to server log file!
      }
 }

This is the BPM code. I don’t know where to put it and I’ve tried different ways just end up with errors that make no sense!

if your second priority -when not null- is estQty over compQty then your line should be:
decimal laborQty = overQty>0?overQty:estQty>0?estQty:compQty;
image

Thank you’ve updated it now :smiley: Still trying to work out this case when now! I love learning C#

Hi @aarong ,
you mean using C# - Ternary Operator ?: short if then else condition, ok, try this :

Decimal cEstLabourHours_recalculated = r.JobOper.SetupOpr_c==1 && r.JobOper.QtyCompleted==1?0:r.JobOper.SetupOpr_c==1&&r.JobOper.OverrideQty_c>0?r.JobOper.OverrideQty_c*r.JobOper.EstSetHours:r.JobOper.SetupOpr_c==0?(r.JobOper.ProdStandard*(r.JobOper.RunQty-r.JobOper.QtyCompleted)/60):0; 
1 Like