C# Code help anyone?

,

Where is the line or code where you are updating Character03? Can you paste that. In the above code doesnt look like your updating anything.

Ah yes, sorry. I took it out when I was trying to update Character03 elsewhere. I have pasted it under the ContextBpm lines.

What method is this running on? And is it pre or post?

It is pre at the moment Jose, I have tried it in post but I got the dreaded ‘Line is being updated by another user’ error. so I moved it back. I tried just doing the update in post using the ContextBpm fields but that did not work either.

I think its because hes throwing an Exception even within the update block, which causes Epicor to reverse the update.

Get rid of

throw new Ice.Common.BusinessObjectException( 
new Ice.Common.BusinessObjectMessage(msg) 
{ 
   Type = Ice.Common.BusinessObjectMessageType.Information, 
});

right after Character03, you already have a PublishInfoMsg below it. For what you are trying to do the PRE is best suited, keep it there.

1 Like

You were right Haso, it updates now but I get this error right at the end;

That now may actually be bad code in your edvOrderHed_EpiViewNotification on the UI Customization. What you got there?

Do you mean BPMs on the OrderHed or customisations on the form itself?

That Error is coming from the Customization Form. Looks like the BPM Executed just fine.

Here is the code attached there. Not written by me I hasten to add. I think it was a third party subcontractor.

// **************************************************
// Custom code for QuoteForm
// Created: 3/10/2014 11:17:37 PM
// **************************************************
using System;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Windows.Forms;
using Ice.Adapters;
using Erp.UI;
using Ice.Lib.Customization;
using Ice.Lib.Framework;
using Ice.Lib.ExtendedProps;
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 edvQuoteHed;
	private EpiDataView edvQuoteDtl;
	private EpiDataView edvCallContextBpmData;
	private EpiDataView edvOrderHed;
	// End Wizard Added Module Level Variables **

	// Add Custom Module Level Variables Here **

	private bool bProjectFlag = false;
	private string sProjectID = string.Empty;
	private string sPhaseID = string.Empty;

	public void InitializeCustomCode()
	{
		// ** Wizard Insert Location - Do not delete 'Begin/End Wizard Added Variable Initialization' lines **
		// Begin Wizard Added Variable Initialization

		this.edvQuoteHed = ((EpiDataView)(this.oTrans.EpiDataViews["QuoteHed"]));	
		this.edvQuoteDtl = ((EpiDataView)(this.oTrans.EpiDataViews["QuoteDtl"]));
		this.edvQuoteDtl.EpiViewNotification += new EpiViewNotification(this.edvQuoteDtl_EpiViewNotification);
		this.edvCallContextBpmData = ((EpiDataView)(this.oTrans.EpiDataViews["CallContextBpmData"]));
		this.edvCallContextBpmData.EpiViewNotification += new EpiViewNotification(this.edvCallContextBpmData_EpiViewNotification);
		this.edvOrderHed = ((EpiDataView)(this.oTrans.EpiDataViews["OrderHed"]));
		this.edvOrderHed.EpiViewNotification += new EpiViewNotification(this.edvOrderHed_EpiViewNotification);
		this.edvQuoteHed.EpiViewNotification += new EpiViewNotification(this.edvQuoteHed_EpiViewNotification);
		// End Wizard Added Variable Initialization

		// Begin Wizard Added Custom Method Calls

		CreateRowRuleQuoteDtlCheckBox06Equals_True();;
		this.ProjBtn.Click += new System.EventHandler(this.ProjBtn_Click);
		this.PhaseBtn.Click += new System.EventHandler(this.PhaseBtn_Click);
		// 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.edvQuoteHed = null;
		this.edvQuoteDtl.EpiViewNotification -= new EpiViewNotification(this.edvQuoteDtl_EpiViewNotification);
		this.edvQuoteDtl = null;
		this.edvCallContextBpmData.EpiViewNotification -= new EpiViewNotification(this.edvCallContextBpmData_EpiViewNotification);
		this.edvCallContextBpmData = null;
		this.edvOrderHed.EpiViewNotification -= new EpiViewNotification(this.edvOrderHed_EpiViewNotification);
		this.edvOrderHed = null;
		this.ProjBtn.Click -= new System.EventHandler(this.ProjBtn_Click);
		this.PhaseBtn.Click -= new System.EventHandler(this.PhaseBtn_Click);
		this.edvQuoteHed.EpiViewNotification -= new EpiViewNotification(this.edvQuoteHed_EpiViewNotification);
		// End Wizard Added Object Disposal

		// Begin Custom Code Disposal

		// End Custom Code Disposal
	}


	private void edvQuoteDtl_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.AddRow))
		{
			if (bProjectFlag == true)
			{
				
				string[] sArr = edvCallContextBpmData.dataView[edvCallContextBpmData.Row]["Character01"].ToString().Split('~');			
//				for(int i=0;i<=sArr.Length;i++)
//				{
//					MessageBox.Show(sArr[i].ToString());
//				}
				view.dataView[view.Row].BeginEdit();
				view.dataView[view.Row]["ProjectID"] = sArr[0].ToString();
				view.dataView[view.Row]["PhaseID"] = sArr[1].ToString();
				view.dataView[view.Row].EndEdit();
				edvQuoteHed.Notify(new EpiNotifyArgs(oTrans,edvQuoteHed.dataView.Count - 1,EpiTransaction.NotifyType.Initialize));
				bProjectFlag = false;	
				edvCallContextBpmData.dataView[edvCallContextBpmData.Row].BeginEdit();
				edvCallContextBpmData.dataView[edvCallContextBpmData.Row]["Character01"] = string.Empty;
				edvCallContextBpmData.dataView[edvCallContextBpmData.Row].EndEdit();			
			}
		}
	}

	private void edvCallContextBpmData_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(view.dataView[view.Row]["CheckBox01"].ToString().ToLower().Equals("true"))
		{
			//MessageBox.Show("OK");
			view.dataView[view.Row].BeginEdit();
			view.dataView[view.Row]["CheckBox01"] = false;
			view.dataView[view.Row].EndEdit();
			bProjectFlag = true;
			oTrans.GetNewQuoteDtl();	
		}
	}

	private void edvOrderHed_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.AddRow))
		//{
		if ((args.Row > -1))
		{
		//	}
		//}
			if (bProjectFlag == true)
			{
				
				string[] sArr = edvCallContextBpmData.dataView[edvCallContextBpmData.Row]["Character01"].ToString().Split('~');			
//				for(int i=0;i<=sArr.Length;i++)
//				{
//					MessageBox.Show(sArr[i].ToString());
//				}
				view.dataView[0].BeginEdit();								
				view.dataView[0]["ShortChar01"] = sArr[2].ToString();
				view.dataView[0].EndEdit();			
								
			}
		}
	}

	

	private void CreateRowRuleQuoteDtlCheckBox06Equals_True()
	{
		// Description: Line Ordered
		// **** begin autogenerated code ****
		RuleAction highlightQuoteDtl_QuoteLine = RuleAction.AddControlSettings(this.oTrans, "QuoteDtl.QuoteLine", SettingStyle.Highlight);
		RuleAction[] ruleActions = new RuleAction[] {
				highlightQuoteDtl_QuoteLine};
		// Create RowRule and add to the EpiDataView.
		RowRule rrCreateRowRuleQuoteDtlCheckBox06Equals_True = new RowRule("QuoteDtl.CheckBox06", RuleCondition.Equals, true, ruleActions);
		((EpiDataView)(this.oTrans.EpiDataViews["QuoteDtl"])).AddRowRule(rrCreateRowRuleQuoteDtlCheckBox06Equals_True);
		// **** end autogenerated code ****
	}


	private void SearchOnProjectAdapterShowDialog()
	{
		// Wizard Generated Search Method
		// You will need to call this method from another method in custom code
		// For example, [Form]_Load or [Button]_Click

		bool recSelected;
		string whereClause = string.Empty;
		System.Data.DataSet dsProjectAdapter = Ice.UI.FormFunctions.SearchFunctions.listLookup(this.oTrans, "ProjectAdapter", out recSelected, true, whereClause);
		if (recSelected)
		{
			System.Data.DataRow adapterRow = dsProjectAdapter.Tables[0].Rows[0];

			// Map Search Fields to Application Fields
			EpiDataView edvQuoteHed = ((EpiDataView)(this.oTrans.EpiDataViews["QuoteHed"]));
			System.Data.DataRow edvQuoteHedRow = edvQuoteHed.CurrentDataRow;
			if ((edvQuoteHedRow != null))
			{
				edvQuoteHedRow.BeginEdit();
				edvQuoteHedRow["ProjectID_c"] = adapterRow["ProjectID"];
				edvQuoteHedRow["ProjectDescription_c"] = adapterRow["Description"];
				edvQuoteHedRow.EndEdit();
				ProjDesc.Text = Convert.ToString(adapterRow["Description"]);
				SearchOnProjPhaseSearchAdapterShowDialog();
			}
		}
	}

	private void SearchOnProjectAdapterNoShowDialog()
	{
		ProjDesc.Text = "";
		// Wizard Generated Search Method
		// You will need to call this method from another method in custom code
		// For example, [Form]_Load or [Button]_Click
		EpiDataView edvQuoteHed = ((EpiDataView)(this.oTrans.EpiDataViews["QuoteHed"]));
		System.Data.DataRow edvQuoteHedRow = edvQuoteHed.CurrentDataRow;
		if ((edvQuoteHedRow != null))
		{
			bool recSelected;
			string whereClause = string.Empty;
			string sProjID = string.Empty;
			sProjID = Convert.ToString(edvQuoteHedRow["ProjectID_c"]);
			if (sProjID != "")
			{
				whereClause = "ProjectID = '" + sProjID + "'";
				System.Data.DataSet dsProjectAdapter = Ice.UI.FormFunctions.SearchFunctions.listLookup(this.oTrans, "ProjectAdapter", out recSelected, false, whereClause);
				if (recSelected)
				{
					System.Data.DataRow adapterRow = dsProjectAdapter.Tables[0].Rows[0];
			// Map Search Fields to Application Fields
					ProjDesc.Text = Convert.ToString(adapterRow["Description"]);
				}
			}
		}
	}

	private void ProjBtn_Click(object sender, System.EventArgs args)
	{
		// ** Place Event Handling Code Here **
		SearchOnProjectAdapterShowDialog();
	}

	private void PhaseBtn_Click(object sender, System.EventArgs args)
	{
		// ** Place Event Handling Code Here **
		SearchOnProjPhaseSearchAdapterShowDialog();
	}

	private void SearchOnProjPhaseSearchAdapterShowDialog()
	{
		// Wizard Generated Search Method
		// You will need to call this method from another method in custom code
		// For example, [Form]_Load or [Button]_Click
		EpiDataView edvQuoteHed = ((EpiDataView)(this.oTrans.EpiDataViews["QuoteHed"]));
		System.Data.DataRow edvQuoteHedRow = edvQuoteHed.CurrentDataRow;
		if ((edvQuoteHedRow != null))
		{
			bool recSelected;
			string whereClause = string.Empty;
			string sProjID = string.Empty;
			sProjID = Convert.ToString(edvQuoteHedRow["ProjectID_c"]);
			if (sProjID != "")
			{
				whereClause = "ProjectID = '" + sProjID + "'";
			}
			System.Data.DataSet dsProjPhaseSearchAdapter = Ice.UI.FormFunctions.SearchFunctions.listLookup(this.oTrans, "ProjPhaseSearchAdapter", out recSelected, true, whereClause);
			if (recSelected)
			{
				System.Data.DataRow adapterRow = dsProjPhaseSearchAdapter.Tables[0].Rows[0];

			// Map Search Fields to Application Fields
				edvQuoteHedRow.BeginEdit();
				edvQuoteHedRow["PhaseID_c"] = adapterRow["PhaseID"];
				edvQuoteHedRow["PhaseDescription_c"] = adapterRow["Description"];
				edvQuoteHedRow.EndEdit();
				PhaseDesc.Text = Convert.ToString(adapterRow["Description"]);
			}
		}
	}

	private void SearchOnProjPhaseSearchAdapterNoShowDialog()
	{
		PhaseDesc.Text = "";
		// Wizard Generated Search Method
		// You will need to call this method from another method in custom code
		// For example, [Form]_Load or [Button]_Click
		EpiDataView edvQuoteHed = ((EpiDataView)(this.oTrans.EpiDataViews["QuoteHed"]));
		System.Data.DataRow edvQuoteHedRow = edvQuoteHed.CurrentDataRow;
		if ((edvQuoteHedRow != null))
		{
			bool recSelected;
			string whereClause = string.Empty;
			string sProjID = string.Empty;
			sProjID = Convert.ToString(edvQuoteHedRow["ProjectID_c"]);
			sPhaseID = Convert.ToString(edvQuoteHedRow["PhaseID_c"]);
			if (sProjID != "")
			{
				whereClause = "ProjectID = '" + sProjID + "'";
				if (sPhaseID != "")
				{
					whereClause = whereClause + " and PhaseID = '" + sPhaseID + "'";
					System.Data.DataSet dsProjPhaseSearchAdapter = Ice.UI.FormFunctions.SearchFunctions.listLookup(this.oTrans, "ProjPhaseSearchAdapter", out recSelected, false, whereClause);
					if (recSelected)
					{
						System.Data.DataRow adapterRow = dsProjPhaseSearchAdapter.Tables[0].Rows[0];
			// Map Search Fields to Application Fields
						PhaseDesc.Text = Convert.ToString(adapterRow["Description"]);
					}
				}
			}
		}
	}

	private void edvQuoteHed_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.AddRow))
		//{
			if ((args.Row > -1))
			{
				SearchOnProjectAdapterNoShowDialog();
				SearchOnProjPhaseSearchAdapterNoShowDialog();
			}
		//}
	}
}

I think I found the problem. the customisation code uses BPMContext Data character01 as well. I took it out of the Reference BPM and the error went away. Thanks Haso, you’re the best!!

2 Likes

Hi guys, I seem to have hit a problem. I thought this worked but in our live system where the order qty and Character03 are populated by the configurator, the BPM is not formatting Character03. Does it recognise the configurator has made an update? Or does the configurator populate the field after the BPM? I am getting the messages so I know the BPM is firing but Character03 is exactly the way it comes from the configurator.
@ckrusen @hkeric.wci

It’s possible the BPM is doing it’s job, but the UI is lagging behind the updated data.

Have you run a trace to see the orde of the calls, and what data is being changed by each?

A BPM usually carries 2 row records in most cases… The Unchanged row (aka the historical, previous row) and Changed Row (with the proposed values). Wherever you are assigning Character03, make sure you are assigning it with the value of the Changed Row… RowMod of U or A.

If you gave us more code to give us more context, we can see what your doing.

The code from post #29 has Character01, and ShortChar01

Did you update them both to “03” ??

This is the process from the start as I have it now. Character03 is populated by the document rules from the configurator like this;

switch (Context.Entity)
{
	case "QuoteDtl":
		QuoteDtl.LineDesc = Inputs.fbPartNumber.Value;
    QuoteDtl.PricingQty = Inputs.decQty.Value;
    QuoteDtl.SellingExpectedQty = Inputs.decQty.Value;
    QuoteDtl.OrderQty = Inputs.decQty.Value;
    QuoteDtl["Number01"] = Inputs.decQuoteCost.Value;
    QuoteDtl["Number02"] = Inputs.decGlobalMaterialCost.Value;
    QuoteDtl["Number03"] = Inputs.decGlobalLabourCost.Value;
    QuoteDtl["Number05"] = Inputs.decScrapCost.Value;
    QuoteDtl["Character01"] = Inputs.edBody.Value;
    QuoteDtl["Character03"] = Inputs.edReferenceComments.Value;   
    QuoteDtl["CheckBox03"] = Inputs.cbNonStandardProduct.Value;
		if (Inputs.cbNonStandardProduct.Value)
		{
			QuoteDtl.OriginalPartNo_c = Inputs.edDescription.Value;
		}
		break;

This works and the references are populated on the quote form.
image
The BPM fires and everything is good so far


However the values from the BPM are not being saved to the quote, character03 would stay the same anyway but character04 is empty
image
Incidentally the reason for the two different string values is Character03 will be printed on the quote as it is more tidy and compact, character04 is in the format required for our label printer.
Here is the BPM

var ttQuoteDtl_iterator = (from ttQuoteDtl_Row in ttQuoteDtl
                         where (ttQuoteDtl_Row.RowMod == "U")
                         select ttQuoteDtl_Row).FirstOrDefault();

// Check if a row exists.
// If it does make sure there are no extra commas or line feeds
// Get quantity required
int qty = Convert.ToInt32(ttQuoteDtl_iterator.OrderQty);
int qtyRefs = 0;
bool stringCorrect = false;
string msg = "";
if (ttQuoteDtl_iterator != null)
{
	
	string refs = ttQuoteDtl_iterator["Character03"].ToString();
	refs = refs.Replace("\r",",");
	refs = refs.Replace("\n",",");
	refs = refs.Replace(", ,",",");
	refs = refs.Replace(",,",",");
	ttQuoteDtl_iterator["Character03"] = refs.Trim(',');


	

//string refs = "ref1,reff2,ref3,ref4,ref5,ref10[5]";
		
	string[] arr = refs.Split(',');
	string exp = "";
	
	foreach( string el in arr){
		//exp = exp + el + ',';
		int j;			// num in brackets for counting
		string s="";	// the prat before the brackets
		
			
		Regex r = new Regex(@"^(?<rf>.+)\[(?<c>.*)\]",RegexOptions.None, TimeSpan.FromMilliseconds(150));
		
		Match m = r.Match(el);
		 if (m.Success){
			 s = r.Match(el).Result("${rf}");
			 j = Convert.ToInt32(r.Match(el).Result("${c}"));
			 while(j>0){
				 exp = exp + s + ',';
				 j--;
				 }
			 }
		else{
			 exp = exp + el + ',';
			}
		}
	// Get number of refs in string;
	exp = exp.Trim(',');
	qtyRefs = exp.Split(',').Count();	

	if ((qty >= 1 && qtyRefs  == 1) || qty == qtyRefs)
		{
			stringCorrect  = true;
			ttQuoteDtl_iterator["Character04"] = exp;

//Diagnostic message
	 msg = "Ref string 4 is " + ttQuoteDtl_iterator["Character04"]  + "\r\n"
						+ "Ref string 3 is " + ttQuoteDtl_iterator["Character03"]  + "\r\n"
						+ "Order Qty is  " + qty + "\r\n"
						+ "Qty of refs is " + qtyRefs  + "\r\n"
						+ "Refs correct is " + stringCorrect;

						throw new Ice.Common.BusinessObjectException( 
						new Ice.Common.BusinessObjectMessage(msg) 
						{ 
							Type = Ice.Common.BusinessObjectMessageType.Information, 
						});

						//this.PublishInfoMessage(msg, Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual, "", "");	
	}
	else
	{
		msg = "References do not match! "  + "\r\n"
					+ "Qty of refs is " + qtyRefs  + "\r\n"
					+ "Order Qty is " + qty  + "\r\n"
					+ "Please check all commas are present and in the correct place.";
						throw new Ice.Common.BusinessObjectException( 
						new Ice.Common.BusinessObjectMessage(msg) 
						{ 
							Type = Ice.Common.BusinessObjectMessageType.Error, 
						} );
	}
Db.Validate();	
}

I thought the two lines

ttQuoteDtl_iterator["Character03"] = refs.Trim(',');

and

ttQuoteDtl_iterator["Character04"] = exp;

would work but it appears not. What to I need to do to get it working?
Many thanks guys for helping.
Adrian.

Hi @Adrian_Mepham,

could you add a show message after each line of those to check the final stamped values in Character03 and Character04 ?

PublishInfoMessage("Character03:"+ttQuoteDtl_iterator[“Character03”],Ice.Common.BusinessObjectMessageType.Error,Ice.Bpm.InfoMessageDisplayMode.Individual,"BusnissObjectName","MethodName");

1 Like

I’m not sure Al but I think you might have helped me solve the problem.

I changed the coding for the message display to be like yours, so I replaced;

throw new Ice.Common.BusinessObjectException( 
						new Ice.Common.BusinessObjectMessage(msg) 
						{ 
							Type = Ice.Common.BusinessObjectMessageType.Information, 
						});

with this

this.PublishInfoMessage(msg, Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual, "", "");

and, touch wood, it appears to be working!
Thanks Al, I shall make a note not to use that kind of message syntax again. Frustrating that I never got an error message about my message though.
Appreciate your help
Adrian.

1 Like