Dashboard Throwing Errors after changing BAQ: "String was not recognized as a valid Boolean. Couldn't store <> in JobHead_JobFirm Column. Expected type is Boolean."

Hello everyone,

########################## BACKGROUND INFORMATION ##########################
I have a dashboard which was built to mirror the existing “Production Planner Workbench” dashboard. The only difference is I have replaced the standard BAQs which drive the Production Planner Workbench with updateable BAQs which allow users to release and firm jobs from this dashboard. There is also a simple customization on this dashboard which allows users to mark all visible jobs on the screen as released via a button click event (code attached below). This is all working without issue - I’m including for context.

Customization code:

    // **************************************************
    // Custom code for MainController
    // Created: 1/15/2020 10:13:17 AM
    // **************************************************
    using System;
    using System.ComponentModel;
    using System.Collections.Generic;
    using System.Data;
    using System.Diagnostics;
    using System.Windows.Forms;
    using Ice.BO;
    using Ice.UI;
    using Ice.Lib;
    using Ice.Adapters;
    using Ice.Lib.Customization;
    using Ice.Lib.ExtendedProps;
    using Ice.Lib.Framework;
    using Ice.Lib.Searches;

    public class Script
    {
	// ** Wizard Insert Location - Do Not Remove 'Begin/End Wizard Added Module Level Variables' Comments! **
	// Begin Wizard Added Module Level Variables **

	// 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.Results_Column.ColumnChanging += new DataColumnChangeEventHandler(this.Results_BeforeFieldChange);
		// End Wizard Added Variable Initialization

		// Begin Wizard Added Custom Method Call		
		this.epiButtonReleaseAll.Click += new System.EventHandler(this.epiButtonReleaseAll_Click);
		this.epiButtonReleaseFull.Click += new System.EventHandler(this.epiButtonReleaseFull_Click);
		this.epiButtonReleaseShortage.Click += new System.EventHandler(this.epiButtonReleaseShortage_Click);
		// End Wizard Added Custom Method Calls

		//this.baseToolbarsManager.Tools["SaveTool"].ToolClick += new Infragistics.Win.UltraWinToolbars.ToolClickEventHandler(this.SaveButton_Click);
	}

	public void DestroyCustomCode()
	{
		// ** Wizard Insert Location - Do not delete 'Begin/End Wizard Added Object Disposal' lines **
		// Begin Wizard Added Object Disposal		
		this.epiButtonReleaseAll.Click -= new System.EventHandler(this.epiButtonReleaseAll_Click);
		this.epiButtonReleaseFull.Click -= new System.EventHandler(this.epiButtonReleaseFull_Click);
		this.epiButtonReleaseShortage.Click -= new System.EventHandler(this.epiButtonReleaseShortage_Click);
		this.Results_Column.ColumnChanging -= new DataColumnChangeEventHandler(this.Results_BeforeFieldChange);
		// End Wizard Added Object Disposal

		// Begin Custom Code Disposal

		// End Custom Code Disposal

		//this.baseToolbarsManager.Tools["SaveTool"].ToolClick -= new Infragistics.Win.UltraWinToolbars.ToolClickEventHandler(this.SaveButton_Click);
	}

	private void epiButtonReleaseAll_Click(object sender, System.EventArgs args)
	{
		// ** Place Event Handling Code Here **
		if (MessageBox.Show("Are you sure you want to release ALL JOBS?", "Confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
		{	
			EpiDataView dv = (EpiDataView)(oTrans.EpiDataViews["V_UD_uProductionPlannerJobs_2_1View3"]);
			DataView datView = dv.dataView;
			foreach(DataRowView rowView in datView)
			{
				rowView.Row["JobHead_JobReleased"] = true;
				//rowView.Row["JobHead_JobFirm"] = true;
			}
		}
	}

	private void epiButtonReleaseFull_Click(object sender, System.EventArgs args)
	{
		// ** Place Event Handling Code Here **
		if (MessageBox.Show("Are you sure you want to release all visible jobs with FULL AVAILABILITY?", "Confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
		{	
			EpiDataView dv = (EpiDataView)(oTrans.EpiDataViews["V_UD_uProductionPlannerJobs_2_1View1"]); // V_UD_uProductionPlannerJobs_2_1View3 = ALL JOBS
			DataView datView = dv.dataView;
			foreach(DataRowView rowView in datView)
			{
				rowView.Row["JobHead_JobReleased"] = true;
				//rowView.Row["JobHead_JobFirm"] = true;
			}
		}
	}

	private void epiButtonReleaseShortage_Click(object sender, System.EventArgs args)
	{
		// ** Place Event Handling Code Here **
		if (MessageBox.Show("Are you sure you want to release all SHORTAGE JOBS?", "Confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
		{	
			EpiDataView dv = (EpiDataView)(oTrans.EpiDataViews["V_UD_uProductionPlannerJobs_2_1View2"]); // V_UD_uProductionPlannerJobs_2_1View1 = Full only
			DataView datView = dv.dataView;
			foreach(DataRowView rowView in datView)
			{
				rowView.Row["JobHead_JobReleased"] = true;
				//rowView.Row["JobHead_JobFirm"] = true;
			}
		}
	}

	private void Results_BeforeFieldChange(object sender, DataColumnChangeEventArgs args)
	{
		// ** Argument Properties and Uses **
		// args.Row["FieldName"]
		// args.Column, args.ProposedValue, args.Row
		// Add Event Handler Code
		switch (args.Column.ColumnName)
		{
			case "JobHead_JobReleased":
				if ((bool)args.ProposedValue == true)
				{
					args.Row["JobHead_JobFirm"] = true;
				}
				break;
		}
	}

Our users recently added a new request for this dashboard to include a 12 month running total of how often the specific part on a job has been used. Simple. I updated the BAQs driving this dashboard to look in the PartTran table for each time a ‘STK-CUS’ trantype occurs and for lower level parts, for every time a ‘STK-MTL’ trantype occurs. The new queries are working as expected.

######################## END BACKGROUND INFORMATION ########################

NOW - on to the issue. After these queries were created, I updated the dashboard to use the new queries (I made new queries instead of updating the originals so I could roll back worst case scenario), and everything is displaying as it should. However, whenever I attempt to use any of the button controls to release jobs, I receive the following error:

Error text: “String was not recognized as a valid Boolean. Couldn’t store <> in JobHead_JobFirm Column. Expected type is Boolean”.

Simple error to fix… at least it should be. Debugging in visual studio, the error occurs on the following line in any of the button control click events:

args.Row["JobHead_JobFirm"] = true;

Full event code:

private void Results_BeforeFieldChange(object sender, DataColumnChangeEventArgs args)
{
	// ** Argument Properties and Uses **
	// args.Row["FieldName"]
	// args.Column, args.ProposedValue, args.Row
	// Add Event Handler Code
	switch (args.Column.ColumnName)
	{
		case "JobHead_JobReleased":
			if ((bool)args.ProposedValue == true)
			{
				args.Row["JobHead_JobFirm"] = true;
			}
			break;
	}
}

As you can see, I am not attempting to store a string in args.Row[“JobHead_JobFirm”], but I’m not sure if something is happening up stream which would cause this.

Note that since I am using a different BAQ, I had to update button control’s click event code. The EpiDataView’s name I use to create the “dv” object had to be changed to reflect the new EpiDataView. Nothing in the code has been touched other than this

Original click event for the same button:

EpiDataView dv = (EpiDataView)(oTrans.EpiDataViews["V_UD_uProductionPlannerJobs_2_1View1"]);

Code after changing query:

EpiDataView dv = (EpiDataView)(oTrans.EpiDataViews["V_UD_uProductionPlannerJobs_usg_1View1"]);

Nothing else changed.

One final note to complicate things even further - this recently stopped occurring on my local machine as I was debugging in visual studio. I had made no code changes and thought this was odd. I went to another machine to test this and the error still occurs on that second machine. I still receive the error on my own workstation on occasion, but it’s much rarer now.

Why did you comment out

//rowView.Row["JobHead_JobFirm"] = true;

?

I wonder if you need to set that as true or false before updating the row? At the very end there on your if/JobReleased condition you might try adding an else { JobFirm = false }, as it looks like it might be trying to update the row with a null value there.

Also, whenever I get inconsistent results on customizations between workstations, clearing Epicor’s cache usually fixes it. i.e. (C:\Users\All Users\Epicor\epicor10-808\3.1.500.0\ )

Hey Jeff!

Thanks for taking the time to respond - I need to edit my original post as I copied the wrong line of code. The error is being thrown within the “Results_BeforeFieldChange” event:

private void Results_BeforeFieldChange(object sender, DataColumnChangeEventArgs args)
	{
		// ** Argument Properties and Uses **
		// args.Row["FieldName"]
		// args.Column, args.ProposedValue, args.Row
		// Add Event Handler Code
		switch (args.Column.ColumnName)
		{
			case "JobHead_JobReleased":
				if ((bool)args.ProposedValue == true)
				{
					args.Row["JobHead_JobFirm"] = true;
				}
				break;
		}
	}

When setting args.Row[“JobHead_JobFirm”] = true. And good to know on the client cache. Honestly I can delete that line. Originally I was going to firm the job on the button click but users also wanted to just click “Released” and have the job get firmed automatically so I moved that logic into the BeforeFieldChange event.

Have you tried adding an else statement

switch (args.Column.ColumnName)
		{
			case "JobHead_JobReleased":
				if ((bool)args.ProposedValue == true)
				{
					args.Row["JobHead_JobFirm"] = true;
				}
                                else 
                                {
                                        args.Row["JobHead_JobFirm"] = false;
                                }
				break;
		}
	}

Just to be sure that there’s a valid value for each row?

Also, there’s an amazing Visual Studio extension out there that has made my customization debugging so much better. The Epicor “IDE” is fairly lacking…

1 Like

Oh my word! I’m getting this extension ASAP! Thank you so much!

I only want to update JobHead_JobFirm when the user has changed the JobHead_JobReleased column to true. In all other scenarios, I want JobHead_JobFirm to remain unchanged from what was returned by the BAQ. If I include something like

else
{
     args.Row["JobHead_JobFirm"] = false;
}

that would update JobHead_JobFirm to false if the user decided to UN-Release a job (unless I’m mistaken).

EDIT:
Even as I hit “reply” I realized my error - that block won’t run at all if a job is unreleased as args.ProposedValue will be “false” in that scenario. I’m just worried about unfirming a job unintentionally.

Gotcha.

Yeah that extension is amazing. With that you’ll be able to inspect the data objects while it’s running and hopefully see what the heck is going on here.

Update:

Unfortunately adding an “else” block doesn’t affect the behavior. The error still is complaining about me assigning a string to a boolean - which I am not… lol

Did you get VS extensions? If you debug with that you can view the value of the object in question while it’s running.

Unfortunately, the VS extension throws errors when I open this customization.



It thinks “this.Results_Column” doesn’t exist. However, I can continue what I have been doing and just debug using visual studio through Epicor.

Anyway I digress. Below screenshot is from the results view of args.Row.Table.Columns. If I’m reading this correctly, we know from this that JobHead_JobFirm is Row index 15:

Taking a look at args.Row at index 15, we can see that it is in fact a boolean

I also added a line to print out the type of args.Row[“JobHead_JobFirm”] just in case I had misunderstood what I was seeing in debugger:

Added line

MessageBox.Show(args.Row["JobHead_JobFirm"].GetType().ToString());

To the Results_BeforeFieldChange event where the error is originating from:

private void Results_BeforeFieldChange(object sender, DataColumnChangeEventArgs args)
{
	// ** Argument Properties and Uses **
	// args.Row["FieldName"]
	// args.Column, args.ProposedValue, args.Row
	// Add Event Handler Code
	switch (args.Column.ColumnName)
	{
		case "JobHead_JobReleased":
			if ((bool)args.ProposedValue == true)
			{
             MessageBox.Show(args.Row["JobHead_JobFirm"].GetType().ToString());
				args.Row["JobHead_JobFirm"] = true;
			}
			break;
	}
}

Sure enough - Boolean

Well that is frustrating. Everything looks right to me.

Have you run a trace on it? Not sure it would do a whole lot of good but that’s probably what I would try next.

Apologies for the very late response. I got pulled away on other projects and looks like this will be on the back burner for a little while yet. Let me just say thank you Jeff for taking the time to respond. I really do appreciate it :slight_smile:

Running a trace didn’t reveal much unfortunately. The only method that runs is DynamicQueryImpl.FieldValidate() and in this method, JobFirm appears as a bit value which I would assume translates to a boolean though I’m not positive.
image
Once I get a chance to circle back to this in detail, I will. Thanks again for your responses. Once I do get this working I’ll let you know what I had wrong.