Labor Qty Reporting BPM

HI,
I have been trying to figure out how to warn users on MES that they are entering a qty other than what was expected. I have found code on here to do that, but it is from E9. Has anyone done this in 10? I am still trying to figure out the new language :blush:

What I found:

/* Stopping Over Reporting of Production Quantities */

 

 

 

  For each ttLaborDtl where ttLaborDtl.RowMod = 'U' and ttLaborDtl.LaborType = "P" no-lock.

 

  

       Find First JobOper Where JobOper.Company = ttLaborDtl.Company and JobOper.JobNum = ttLaborDtl.JobNum and JobOper.AssemblySeq = ttLaborDtl.AssemblySeq and

       JobOper.OprSeq = ttLaborDtl.OprSeq no-lock no-error.

      

         If avail JobOper Then Do:

        

                                If JobOper.QtyCompleted + ttLaborDtl.LaborQty > JobOper.RunQty and ttLaborDtl.EnableRequestMove = yes Then DO:

        

                                                 {lib/PublishEx.i &ExMsg = "'There are already ' + String(JobOper.QtyCompleted)  + ' complete. The operation required quantity is ' +

                                                                String(JobOper.RunQty) + '. You entered a quantity of ' +  String(ttLaborDtl.LaborQty) + ' this will result in over reported quantities.'"}.

        

                                                                 assign ttLaborDtl.LaborQty = 0.

        

                                End.

      

         End.

      

       Else.

      

       Find First labordtl where labordtl.company = ttlabordtl.company and labordtl.LaborDtlSeq = ttLaborDtl.LaborDtlSeq no-lock no-error.

      

         if avail LaborDtl Then DO:

        

                Define Variable oldLaborQty as integer no-undo.

        

                assign oldLaborQty = LaborDtl.LaborQty.

        

                                If (JobOper.QtyCompleted - oldLaborQty) + ttLaborDtl.LaborQty > JobOper.RunQty  and ttLaborDtl.EnableRequestMove = no Then DO:

        

                                                                  {lib/PublishEx.i &ExMsg = "'There are already ' + String(JobOper.QtyCompleted)  + ' complete. The operation required quantity is ' +

                                                                 String(JobOper.RunQty) + '. You entered a quantity of' +  String(ttLaborDtl.LaborQty) + ' this will result in over reported quantities.'"}.

        

                                                                                 assign ttLaborDtl.LaborQty = 0.

        

                                End.

      

                 End.

 

  

  End.

I built that check into the screen itself since all the info you need to do that check should be there.

1 Like

Thanks for the suggestion. Unfortunatley we use the End Activity screen in MES and the required quantity is not anywhere on the screen. Maybe I can customize the screen to add that and then do as you suggest :slight_smile:
I will give it a try.
Thanks

You could add a FKV for JobOper into the screen and use the runqty field that would be the operation specific qty with any scrap factors I believe. Alternatively you could do a BPM pre-process on Labor.Update where EndActivity = true that would be your basic filter of what you are looking for. From there the process would be similar, do a lookup on JobOper for the run qty then compare to what current and already completed for the oper is and throw a message or don’t

That looks like the routine i got off of the Vantage group. This is the converted code. We are still testing E10 and I am not sure this has been tested, but it does compile.


/* Stopping Over Reporting of Production Quantities */
string Customer = string.Empty;
Erp.Tables.JobHead JobHead;
Erp.Tables.JobOper JobOper;
Erp.Tables.LaborDtl LaborDtl;

             var orgLaborDtl = (from Old_Row in ttLaborDtl
                                where Old_Row.RowMod == ""
                                select Old_Row).FirstOrDefault();
        

 foreach(var ttLaborDtl_iterator in(from ttLaborDtl_Row in ttLaborDtl
 where ttLaborDtl_Row.Updated() && (string.Compare(ttLaborDtl_Row.LaborType,"P",true)== 0 || string.Compare(ttLaborDtl_Row.LaborType,"S",true)== 0)
 select ttLaborDtl_Row))
    {
      var ttLaborDtlRow = ttLaborDtl_iterator;
        
      
      if(string.Compare(ttLaborDtlRow.LaborType,"P",true)== 0)
       {
       JobHead =(from JobHead_Row in Db.JobHead
       where string.Compare(JobHead_Row.Company,ttLaborDtlRow.Company,true)== 0 && string.Compare(JobHead_Row.JobNum,ttLaborDtlRow.JobNum,true)== 0
       select JobHead_Row).FirstOrDefault();
        
       if(JobHead != null)
          {
 
      
            JobOper = (from JobOper_Row in Db.JobOper
                            where string.Compare(ttLaborDtlRow.Company, JobOper_Row.Company, true) == 0 && string.Compare(ttLaborDtlRow.JobNum, JobOper_Row.JobNum, true) == 0 && ttLaborDtlRow.AssemblySeq == JobOper_Row.AssemblySeq && ttLaborDtlRow.OprSeq == JobOper_Row.OprSeq                           
                            select JobOper_Row).FirstOrDefault();
            if (JobOper != null)
            {
       
                 if(JobOper.QtyCompleted+ttLaborDtlRow.LaborQty > JobOper.RunQty && ttLaborDtlRow.EnableRequestMove == true)
                  {
                  CallContext.Current.ExceptionManager.AddBLException("There are already " + JobOper.QtyCompleted  + " complete. The operation required quantity is " +  JobOper.RunQty + ". You entered a quantity of " +  
                                                                       ttLaborDtlRow.LaborQty + " this will result in over reported quantities.");
                  ttLaborDtlRow.LaborQty = 0;
                  }
       
            }
            else
            {


               var oldLaborQty = System.Convert.ToInt32(orgLaborDtl.LaborQty);
               if((JobOper.QtyCompleted -oldLaborQty)+ttLaborDtlRow.LaborQty > JobOper.RunQty  && ttLaborDtlRow.EnableRequestMove == false)
              {
               CallContext.Current.ExceptionManager.AddBLException("There are already " + JobOper.QtyCompleted  + " complete. The operation required quantity is " + 
                                                                     JobOper.RunQty + ". You entered a quantity of " +  ttLaborDtlRow.LaborQty.ToString("####") + " this will result in over reported quantities.");
                ttLaborDtlRow.LaborQty = 0;
              }

             }
      
          }
      
        }
      
      
      

    }
  

-in my opinion- the easiest way to do this is as @jgiese.wci said BPM pre-process on Labor.Update where EndActivity = true, work out your logic with regard to the Qty, then apply it in the code, i.e. in my environment (Total Completed Qty Per each Operation + Total NCR Qty Per each Operation must be equal or less than Job Production Qty) Note: Yield calculation must correct the Job Production Qty between Operations.

as labor can not enter anything in Scrap field ( it should be done by QC according to different report procedure)

i have done something similar to calculate the total completed setup percentage of all previous labor transactions for any setup type operation at End Activity, i can sure it with you and you can alter it to suit your use.

It’s likely that would work with minor tweaking however it’s incredibly lengthy for the task LOL. That code could be summed up into about 20 lines.

ominous tone bewaaaaare the converter whooooooo spoooooky

1 Like

@jgiese.wci True, but one has to start somewhere and since I am only a month into this, it is a better starting point than trying to do all of my bpms by hand.

For sure, but for real beware the converter it can really create some issues.

So your basic roadmap is this

  1. Set up an event fire this off. Probably a leave field event, or change value, can be easily set up with the wizard.
  2. lookup the value you want. This can be done with the JobAdapater or by calling a dynamic query with the values in your DataView. (I would lean towards the dynamic query because I can make queries easier especially when I may need to group/sum records, but that’s my preference)
  3. Compare the values and do something. A message box telling what’s happening, and for us I reset the value so that they can’t over report. This works for our business but may not for yours.

Break this up in to these tasks and work on it incrementally and you will find that it’s not too hard. Copy pasting someone else’s code is a quick fix, but in the end you still won’t know how to do it.

I did this customization on the End Activity screen like @jgiese.wci by adding Job as an FKV and JobOper as a sub table. I set the MaxValue property of the number control as RunQty - QtyCompleted, and I display Total Qty, Qty Completed, and Qty Remaining, for transparency.

I still get users asking me why it won’t let them enter the quantity they did.

(We decided not to do it as a BPM in case there was ever a legitimate use for overrunning the expected quantity. The quantity can still be manually adjusted in Labor Entry.)

1 Like

I am finally getting a chance to try this. I have gotten everything except setting the MaxValue. Where or how do I do this? I can’t find any info in the user guides.
Thanks
Melissa

Add a module level variable:
private EpiNumericEditor numCurrQty;

In InitializeCustomCode, initialize the variable as the number control (and remember to set it back to null in DestroyCustomCode):
this.numCurrQty = (Ice.Lib.Framework.EpiNumericEditor)(this.csm.GetNativeControlReference("f1fdcf24-066d-424e-9b59-319a804854fa"));

Use the wizard to create an event for EpiViewNotification of JobOper, and set the MaxValue there. I have a custom numeric editor for displaying the expected quantity left on the operation, so I use that instead of a decimal variable. That’s what I set to RunQty - QtyCompleted. If the current transaction is rework, I set the max value to the run quantity, so rework can actually be recorded when the op was already finished. Otherwise, I have a sanity check that the expected quantity remaining is not negative, because it throws an exception if you set a max that’s less than the min.

if ((args.NotifyType == EpiTransaction.NotifyType.Initialize)){
	if ((args.Row > -1)){
		this.numRemain.Value = ((decimal)(view.dataView[args.Row]["RunQty"]) - (decimal)(view.dataView[args.Row]["QtyCompleted"]));
		if((bool)(this.edvEnd.dataView[0]["Rework"])){
        		this.numCurrQty.MaxValue = view.dataView[args.Row]["RunQty"];
		}
		else{	
			this.numCurrQty.MaxValue = (decimal)(this.numRemain.Value) > 0 ? this.numRemain.Value : 0;
		}
	}
}

Apologies if this is unclear–it’s hard to guess what level of experience someone else has.

1 Like

Hi Greg,
Is there a way to make this a warning instead of a hard stop?
Thanks in advance,
Karen

yes, Make the Exception an InfoMessage.Publish

Thanks, Greg!

Greg,
How would I make the Exception an Info Message:

/* Stopping Over Reporting of Production Quantities */
string Customer = string.Empty;
Erp.Tables.JobHead JobHead;
Erp.Tables.JobOper JobOper;
Erp.Tables.LaborDtl LaborDtl;

             var orgLaborDtl = (from Old_Row in ttLaborDtl
                                where Old_Row.RowMod == ""
                                select Old_Row).FirstOrDefault();
        

 foreach(var ttLaborDtl_iterator in(from ttLaborDtl_Row in ttLaborDtl
 where ttLaborDtl_Row.Updated() && (string.Compare(ttLaborDtl_Row.LaborType,"P",true)== 0 || string.Compare(ttLaborDtl_Row.LaborType,"S",true)== 0)
 select ttLaborDtl_Row))
    {
      var ttLaborDtlRow = ttLaborDtl_iterator;
        
      
      if(string.Compare(ttLaborDtlRow.LaborType,"P",true)== 0)
       {
       JobHead =(from JobHead_Row in Db.JobHead
       where string.Compare(JobHead_Row.Company,ttLaborDtlRow.Company,true)== 0 && string.Compare(JobHead_Row.JobNum,ttLaborDtlRow.JobNum,true)== 0
       select JobHead_Row).FirstOrDefault();
        
       if(JobHead != null)
          {
 
      
            JobOper = (from JobOper_Row in Db.JobOper
                            where string.Compare(ttLaborDtlRow.Company, JobOper_Row.Company, true) == 0 && string.Compare(ttLaborDtlRow.JobNum, JobOper_Row.JobNum, true) == 0 && ttLaborDtlRow.AssemblySeq == JobOper_Row.AssemblySeq && ttLaborDtlRow.OprSeq == JobOper_Row.OprSeq                           
                            select JobOper_Row).FirstOrDefault();
            if (JobOper != null)
            {
       
                 if(JobOper.QtyCompleted+ttLaborDtlRow.LaborQty > JobOper.RunQty && ttLaborDtlRow.EnableRequestMove == true)
                  {
                  CallContext.Current.ExceptionManager.AddBLException("There are already " + JobOper.QtyCompleted  + " complete. The operation required quantity is " +  JobOper.RunQty + ". You entered a quantity of " +  
                                                                       ttLaborDtlRow.LaborQty + " this will result in over reported quantities.");
                  ttLaborDtlRow.LaborQty = 0;
                  }
       
            }
            else
            {


               var oldLaborQty = System.Convert.ToInt32(orgLaborDtl.LaborQty);
               if((JobOper.QtyCompleted -oldLaborQty)+ttLaborDtlRow.LaborQty > JobOper.RunQty  && ttLaborDtlRow.EnableRequestMove == false)
              {
               CallContext.Current.ExceptionManager.AddBLException("There are already " + JobOper.QtyCompleted  + " complete. The operation required quantity is " + 
                                                                     JobOper.RunQty + ". You entered a quantity of " +  ttLaborDtlRow.LaborQty.ToString("####") + " this will result in over reported quantities.");
                ttLaborDtlRow.LaborQty = 0;
              }

             }
      
          }
      
        }

Have you tried using Shop Warning for this?

Take this

CallContext.Current.ExceptionManager.AddBLException

to

var InfoMsg = "Your Message Here";
		this.PublishInfoMessage(InfoMsg, Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual, "FirstVar","SecondVar");

Thanks