On the Work Queue, I want a row to be highlighted if it has an Inspection Plan on it.
I was able to use FKV off of the WorkQueue dataview to get the Job dataset and then did a STV to the JobOperInsp table. This is where I hit a dead end since my condition to highlight is (roughly):
The Row Rule Wizard does not seem like it can handle something like that so I tried doing my own code and it failed. Now I am thinking that I would like to use WorkQueue.CheckBox04 to indicate if there is a related row, but I am not sure what Event Type to use.
So, basically I am wondering what Event I should be using to fill the row with this data? Is it Retrieve, AfterAdapterMethod, or something else?
Or, am I going down the completely wrong path and someone has a much better way?
I may get yelled at for this, but a Data Directive on the WorkQueue table can set CheckBox04 for you. Please be aware that a Data Directive Always runs, so be sure to do your homework to write it well. I would only do your work on an Added row, FYI.
Then your RowRule can simply look at that field to highlight.
That field does not exist on the table other than in the Work Queue screen. I could always add a field, but I would rather not as all of the data is there, just need to figure out the right way to get it.
I’m going to try using an adapter instead of creating the views.
If it is not there, then CheckBox04 is from a different table.
However, if that field is currently never populated (Although I would be surprised), you can use a Post-Processing Method Directive BPM when the screen loads the data.
So, I got it working. And by working I mean it does what I want and then crashes out all of Epicor. I know it is because I did the NotifyType as Initialize so it is firing multiple times. Am I toast here and should give up? Or is there something I could do to make this usable?
// **************************************************
// Custom code for WorkQueueForm
// Created: 2/4/2021 2:06:55 PM
// **************************************************
extern alias Erp_Contracts_BO_WorkQueue;
extern alias Erp_Contracts_BO_Labor;
extern alias Erp_Contracts_BO_EmpBasic;
extern alias Erp_Contracts_BO_ResourceGroup;
extern alias Erp_Contracts_BO_Resource;
using System;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Windows.Forms;
using Erp.Adapters;
using Erp.UI;
using Ice.Lib;
using Ice.Adapters;
using Ice.Lib.Customization;
using Ice.Lib.ExtendedProps;
using Ice.Lib.Framework;
using Ice.Lib.Searches;
using Ice.UI.FormFunctions;
public class Script
{
// ** Wizard Insert Location - Do Not Remove 'Begin/End Wizard Added Module Level Variables' Comments! **
// Begin Wizard Added Module Level Variables **
private EpiDataView edvWorkQueue;
// End Wizard Added Module Level Variables **
// Add Custom Module Level Variables Here **
public void InitializeCustomCode()
{
// ** Wizard Insert Location - Do not delete 'Begin/End Wizard Added Variable Initialization' lines **
// Begin Wizard Added Variable Initialization
this.edvWorkQueue = ((EpiDataView)(this.oTrans.EpiDataViews["WorkQueue"]));
this.edvWorkQueue.EpiViewNotification += new EpiViewNotification(this.edvWorkQueue_EpiViewNotification);
// End Wizard Added Variable Initialization
// Begin Wizard Added Custom Method Calls
// End Wizard Added Custom Method Calls
}
public void DestroyCustomCode()
{
// ** Wizard Insert Location - Do not delete 'Begin/End Wizard Added Object Disposal' lines **
// Begin Wizard Added Object Disposal
this.edvWorkQueue.EpiViewNotification -= new EpiViewNotification(this.edvWorkQueue_EpiViewNotification);
this.edvWorkQueue = null;
// End Wizard Added Object Disposal
// Begin Custom Code Disposal
// End Custom Code Disposal
}
private void edvWorkQueue_EpiViewNotification(EpiDataView view, EpiNotifyArgs args)
{
// ** Argument Properties and Uses **
// view.dataView[args.Row]["FieldName"]
// args.Row, args.Column, args.Sender, args.NotifyType
// NotifyType.Initialize, NotifyType.AddRow, NotifyType.DeleteRow, NotifyType.InitLastView, NotifyType.InitAndResetTreeNodes
if ((args.NotifyType == EpiTransaction.NotifyType.Initialize))
{
if ((args.Row > -1))
{
foreach (DataRowView wqRow in edvWorkQueue.dataView)
{
string curJob = wqRow["JobNum"].ToString();
int curAsm = Convert.ToInt32(wqRow["AssemblySeq"]);
int curOp = Convert.ToInt32(wqRow["OprSeq"]);
JobEntryAdapter jeAdapt = new JobEntryAdapter(oTrans);
jeAdapt.BOConnect();
jeAdapt.GetByID(wqRow["JobNum"].ToString());
DataTable dtJOI = jeAdapt.JobEntryData.Tables["JobOperInsp"];
foreach (DataRow drRow in dtJOI.AsEnumerable())
{
if (wqRow["Company"].ToString() == drRow["Company"].ToString() &&
wqRow["JobNum"].ToString() == drRow["JobNum"].ToString() &&
Convert.ToInt32(wqRow["AssemblySeq"]) == Convert.ToInt32(drRow["AssemblySeq"]) &&
Convert.ToInt32(wqRow["OprSeq"]) == Convert.ToInt32(drRow["OprSeq"]))
{
wqRow["CheckBox04"] = true;
}
}
}
}
}
}
}
Yeah doing this in the notify is going to explode your Epicor. Your FKV approach was probably close to what you could do, you could but a Rule on that FKV and have it disable the other view via custom action?
Any reason you aren’t doing a BPM? Doing this in the Customization is going to be much slower. A FKV won’t help as it will only grab on e Job at a time.
Because I would have to create a UD field to hang off of the JobOper table and check to see if there is an Inspection on it. Then if someone deletes the Inspection, I will have to do a BPM to check for that.
If I can figure out how to do it with a Row Rule, then I don’t need to worry about if Inspections are added or removed, I will be checking on the Work Queue if there is a related record in JobOperInsp. To me, trying to make sure I have all of my bases covered through a BPM(s) seems like a difficult route to go.
@hkeric.wci I am trying to use your example where you use the BOReader to check the Customer table but am getting an error with BOReaderImpl and BOReaderSvcContract not existing in Ice.Proxy.Lib and Ice.Contracts. Can you let me know what using and/or assembly I need?
Most screens use a GetList or GetRows Method to bring data to the screen (use a Trace to see what Method is called). If you use a Post-Processing BPM on this, you can populate the CheckBox04 that already exists with whatever value you want. I’ve used this Hijack process many times to save myself a lot of code.
But the CheckBox04 only exists in the DataView. Also, the DataView does not mirror the database, they are all views that were constructed for that screen only.
+1 @Jason_Woods - except I’d do this on a GetXXXXX Method not a Data Directive.
No UD fields need to be created to do this, we are messing with the DataTable/DataSet in memory and we just need to get the RowRule highlight in the client.
I have done something very similar for the Work Queue (and Time Phase) to avoid custom code that might break or have to rewrite later (like in the coming Kinetic).
In the Work Queue case they wanted to see something like days late or something.
I used the WorkQueue.GetOpsInResourceGroup Method Post Processing.
In that BPM it’s just the Update Table by Query widget and I query the Data I want per Job and then assign results to the existing ttWorkQueue Dataset.
In the data there are 5 off the following: Date, Number, ShortChar, Checkbox.
I set the appropriate Query Result values to the fields I wanted and in some cases used an Expression to get the value. Then the only thing I did was customize for the Row Rule evaluating those fields for the rule.
So being a Post Directive Method the TTWorkQueue data is being updated on it’s way back.
I really don’t like messing with FKV when they can be avoided, they are tricky as crap sometimes.
As for covering all your bases with BPM’s, if you have more than one trigger you need to account for (for WorkQueue I found WorkQueue.GetOpsInResourceGroup covered everything in Work Queue) you can instead setup a Function and then just have the right BPM’s call the Function, that way you only have one instance of code to mess with.