Quote Entry Customization - storing unit cost in UD field, loop error

I’m a newbie when it comes to programming in Epicor but have been tasked to update a report to compare the unit cost prices from quote qty breaks and do other calculations. From what I’ve seen from my research, it may be best to write a script in the quote entry screen to store the field in a UD table. Each time I try to engineer the line, I’m getting this error: Collection was modified; enumeration operation might not execute.

Is there a way to have an event trigger off of when a new record is added into quoteqty or after the new record is entered and saved? Then I wouldn’t have to use the foreach statement when the quote detail line is engineered and rather have it done when the new record is added to the table. The only event triggers I’m finding is before/after a row or field update. And most times, values in the row won’t be changed, rather added and left unchanged.

My script:
// **************************************************
// Custom code for QuoteForm
// Created: 11/4/2013 4:20:15 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 Ice.Lib;
using Erp.BO;
using Ice.BO;
using Erp.Proxy.BO;
using Erp.UI;
using Ice.Adapters;
using Erp.Adapters;
using Ice.Lib.Customization;
using Ice.Lib.ExtendedProps;
using Ice.UI.FormFunctions;
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 **
private void quoteQtyGP()
{
	
EpiDataView quoteQtyEdv = (EpiDataView)(oTrans.EpiDataViews["QuoteQty"]);

foreach (DataRow qtyRow in quoteQtyEdv.dataView.Table.Rows)
{

decimal totalCost = Convert.ToDecimal(qtyRow["CalcUnitCost"]);
	qtyRow.BeginEdit();
	qtyRow["TotalCost_c"] = totalCost;
	qtyRow.EndEdit();	
	this.oTrans.Update();
	this.oTrans.Refresh();	

}
}

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

	this.QuoteDtl_Column.ColumnChanged += new DataColumnChangeEventHandler(this.QuoteDtl_AfterFieldChange);
	// 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.QuoteDtl_Column.ColumnChanged -= new DataColumnChangeEventHandler(this.QuoteDtl_AfterFieldChange);
	// End Wizard Added Object Disposal

	// Begin Custom Code Disposal

	// End Custom Code Disposal
}

private void QuoteDtl_AfterFieldChange(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 “ReadyToQuote”:
quoteQtyGP();
break;
}
}

}

1 Like

Let’s consider the task a little bit more. Updating a report doesn’t have anything to do with customization. Are you updating a report or a dashboard? Are you trying to store new information based on a trigger? If so, you could use a method directive (or, god forbid, a data directive) to change or save a value to a field based on an event.

What exactly are you doing with the UD field? Where do you want to store it, and what will it store?

1 Like

The unit cost price on quote price breaks are calculated fields and not stored in the db. I need it stored in a field so I can reference it from the report. Since this is a calculated field, I can’t use BPM’s, but can reference it from a customization from the quote entry screen.

1 Like

Ohhh I see, that is tricky! In this case, the next best step is to run a trace. Do you know how to do that? Trace Helper Utility for Epicor ERP 10 - Epicor ERP 10 - Epicor User Help Forum (epiusers.help)

When you run the trace, it will keep a log of all the methods that are triggered. Then you can use that method to trigger a BPM. I am still not sure about pulling the data from the calculated fields with a BPM. I hope someone else with a bit more know-how can chime in here.

For clarification - are you storing the field in a UD table or on a pre-existing table like QuoteDtl?

I created a new UD field (TotalCost_c) for the quotedtl table.

Try setting the TotalCost_c using the function below

private void OrderDtl_AfterFieldChange(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 “ReadyToQuote”:
			decimal totalCost = Convert.ToDecimal(qtyRow["CalcUnitCost"]);
			
			qtyRow["TotalCost_c"] = totalCost;
			
			break;
	}
	
	this.oTrans.Update();
	this.oTrans.Refresh();	
}

On the OrderDtl table? I’m working on quotes, not sales orders. I’ve tried the before and after field change on the quoteqty table and the event isn’t triggered unless I make a change after the record is entered. That won’t work in most cases, because the price break is entered with the price and it never gets changed after the fact.

@NateS is on the money.

Do a trace and see if that field shows up in the dataset on an update.

We can write your ud field in a bpm.

1 Like

You can check the dataset in a informational message widget.

image

1 Like