Customization Code Review


(John Kane) #1

This is my first time trying to write my own code in Customization instead of using the Wizard. It compiles fine but does not do what I wanted it to do.

I was looking to check if an email address existed on the QuoteHed before a quote could be quoted and error out if not. I wrote the following and was wondering if someone could review real quick and point out if there is a reason why it isn’t working.

	private void chkQuoted_BeforeCheckStateChanged(object sender, System.ComponentModel.CancelEventArgs args)
	{
		var edvQE = oTrans.Factory("QuoteHed");
		if (edvQE.dataView[edvQE.Row]["Quoted"].Equals(false))
		{
			if (edvQE.dataView[edvQE.Row]["EmailAddress"].Equals(null))
			{
				throw new Ice.BLException("No email.");
			}
		}
	}

(Aaron Moreng) #2

which part did you write, the entire method or the contents of the method? You will still need a method handler in the initiation of the code (and a disposal in the disposal method).


(Jose C Gomez) #3

You are comparing the value of an Object to Null however if the object is a string and that string is empty it will not be null. You need to cast that field to a String and then use String.IsNullOrEmpty(myString) to check your condition.


(John Kane) #4

@Aaron_Moreng I wrote the whole thing (obviously leaning on Wizard code I used before) and did not initiate or dispose anything. I had added them in before and they were causing my code to not compile so I too them out. Should I put them back in?

@josecgomez Thanks! I have updated my code with your input, still not working, but that is because of something else I believe.

Do I need to add the initialize and destroy outside of the wizard spots?


(Aaron Moreng) #5

Yes, you will need an event handler implemented in the code in order for this method to do anything. Also, Jose’s suggestion is correct in that you will need to cast the object into a string before checking the condition.
It looks like you’re attempting to trigger this method off of the BeforeCheckStateChanged event of your chkQuoted control. In the Initialize Custom Code method, you will need an event handler that looks something like this:
this.chkQuoted.BeforeCheckStateChanged += new System.EventHandler(this.chkQuoted_BeforeCheckStateChanged);

In the DestroyCustomCode method, you will want the same code but with a “-=” instead of a “+=”.


(Pierre Hogue) #6

But moreover, this request (not accepting save if email is missing) is easily performed via a Method directive Update of Quote …no need of code…
I try to limit changes in the forms if I can use bpm’s…

Pierre


(John Kane) #7

@Aaron_Moreng This is what I got after adding them in. I got the same error for both lines. And yes, I put one in initialize (with the +) and one in destroy (with the -). Do they need to go somewhere specific?

Error: CS1061 - line 50 (826) - ‘Script’ does not contain a definition for ‘chkQuoted’ and no extension method ‘chkQuoted’ accepting a first argument of type ‘Script’ could be found (are you missing a using directive or an assembly reference?)
Error: CS0123 - line 50 (826) - No overload for ‘chkQuoted_BeforeCheckStateChanged’ matches delegate ‘System.EventHandler’

// **************************************************
// Custom code for QuoteForm
// Created: 1/25/2018 12:46:35 PM
// **************************************************

extern alias Erp_Contracts_BO_QuoteDtlSearch;
extern alias Erp_Contracts_BO_Quote;
extern alias Erp_Contracts_BO_Customer;
extern alias Erp_Contracts_BO_AlternatePart;
extern alias Erp_Contracts_BO_Part;
extern alias Erp_Contracts_BO_Vendor;
extern alias Erp_Contracts_BO_VendorPPSearch;
extern alias Erp_Contracts_BO_ShipTo;

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;
using Infragistics.Win.UltraWinToolbars;

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

		// End Wizard Added Variable Initialization

		// Begin Wizard Added Custom Method Calls

		// End Wizard Added Custom Method Calls
		this.chkQuoted.BeforeCheckStateChanged += new System.EventHandler(this.chkQuoted_BeforeCheckStateChanged);
	}

	public void DestroyCustomCode()
	{
		// ** Wizard Insert Location - Do not delete 'Begin/End Wizard Added Object Disposal' lines **
		// Begin Wizard Added Object Disposal

		// End Wizard Added Object Disposal

		// Begin Custom Code Disposal

		// End Custom Code Disposal
		this.chkQuoted.BeforeCheckStateChanged -= new System.EventHandler(this.chkQuoted_BeforeCheckStateChanged);
	}

	private void chkQuoted_BeforeCheckStateChanged(object sender, System.ComponentModel.CancelEventArgs args)
	{
		var edvQE = oTrans.Factory("QuoteHed");
		if (edvQE.dataView[edvQE.Row]["Quoted"].Equals(false))
		{
			string myEA = (string)edvQE.dataView[edvQE.Row]["EmailAddress"];
			if (String.IsNullOrEmpty(myEA))
			{
				throw new Ice.BLException("No email.");
			}
		}
	}

(Aaron Moreng) #8

what is the name of the control you are attempting to go off of?


(John Kane) #9

@Hogardy I had tried using a BPM and it was not working. I had assumed that it was because I was trying to do it on a checkbox. I don’t really want it to get to the update as I don’t believe the update fires on checking it.


(John Kane) #10

@Aaron_Moreng It is the checkbox on the summary page of the quote at the top that you select to mark the record as quoted and enable the ability to print the quote.


(Aaron Moreng) #11

You’ll need the actual control name, from the properties. I would also caution against placing event handling code on native controls; It’s a better technique to go after the underlying dataview and method that changes that data rather than the control behavior.


(John Kane) #12

I’m assuming the (name) under the Misc section?

chkQuoted


(John Kane) #13

Are you suggesting a BPM? I could not get that to work because the Update is not fired when the field is checked. The method that fires is GetQuotedInfo. I did not want to wait until Update to run because I wanted the user to get the feedback right away.

I found a post in here where the native field was hidden and replaced with a custom one and then that custom one was used. I think I will try that.

https://e10help.com/t/warning-message-on-check-box/42419/7


(Pierre Hogue) #14

As a condition, on a new ttQuoteHed, check if the field was changed from anything to 1
it should work. and adding the Exception message avoids a save.

But to resolve your code I think you are missing the access to the Epicor control…in order to use I add a variable pointing to it.

Declare the local object: private EpiCheckBox QuotedChk;

Then add the following in your InitializeCustomCode()

QuotedChk = (EpiCheckBox) csm.GetNativeControlReference(“ae1717bb-1bb2-47f1-ac15-e9e8511080fe”);//where the reference is the GUID of the control

Then add the event declaration
QuotedChk.BeforeCheckStateChanged += new System.EventHandler(this.chkQuoted_BeforeCheckStateChanged);//you can keep your function name…

and in destroy:
QuotedChk.BeforeCheckStateChanged -= new System.EventHandler(this.chkQuoted_BeforeCheckStateChanged);//you can keep your function name…

maybe add a few messagebox to show if it works…if you do not have a debugger…

Hope this helps…


(Pierre Hogue) #15

I missed Aaron comment,

But he is right. You only need to add via the wizard the QuoteHed BeforeFieldChange event and add a case statement for the Quoted field

Do your check on Email and if not present, set args.ProposedValue = false the check should not be present…(add a message to the user to let him know of course… )

Pierre


(John Kane) #16

@Aaron_Moreng @Hogardy

Thanks for all of your input. I’ve been pouring over documentation and better understand the direction that you were suggesting. I am still new to the customization side of Epicor and did not understand the difference between the Form Event and Event wizards.

So, now understanding what the Form Event does, I have been trying to get it to work in my situation and can’t seem to. I was hoping one of you might be able to review what I have and let me know if there is anything wrong.

private void QuoteHed_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 "Quoted":
				EpiDataView edvQuote = ((EpiDataView)(this.oTrans.EpiDataViews["QuoteHed"]));
				string thisEmail = edvQuote.dataView[edvQuote.Row]["EmailAddress"].ToString();
				if ((bool)args.ProposedValue == true && String.IsNullOrEmpty(thisEmail))
				{
					throw new Ice.BLException("No email.");
				}
				break;
		}
	}

(Aaron Moreng) #17

Can you try throwing a message box instead of an Ice.BLException? I am curious if it even gets to that step in your code…

Instead of Throw New, just use MessageBox.Show(“No Email”);


(John Kane) #18

I put the message box in and it now works!?!? I am so confused, but that’s what happens when learning.

I checked the Quoted flag, I got the message box no email, and after clicking ok the Quoted check box was set back to unchecked.

And I just tested with a contact having an email and that worked too!!

I don’t know what the difference between the BLException and the MessageBox is, but that seemed to fix it.


(Aaron Moreng) #19

Excellent! The BLException is not a class I am familiar with, but I’ve seen it used on BPM programming. For form customization and especially since you’re using the beforefieldchange event, a message box should be sufficient.