Custom the Salesperson Quota by ProductGroup

What is the best way to custom the Salesperson Quota, to be able to assign a quota per product group?

I plan to use UDtable and bind it with these fields:
SRepQHed.Company
SRepQHed.FiscalYear
SRepQHed.SalesRepCode

Any ideas to help me achieve this, thank you in advance!!

In a customization, use the wizard to add UD table as child.
Key=FY
Key2=SalesRepCode

In the grid you will set
Key3 = ProdGroup (dropdown)
Number01=Quota

1 Like

Thanks @Jason_Woods !!

I just made my custom UDTable as a child, but I have a problem when pressing the refresh button, it works correctly with fiscal period 1, but not with any other, I don’t know how to explain it, so I generated this gif where you can see the error.

What does your code for this look like? Seems like there could be an issue with the key mapping.

When are you populating the field? Is it an actual DB field or just a control?

Jason Woods
http://LinkedIn.com/in/jasoncwoods

This is the code generated by “Add User Defined Tables As Child Wizard”, I only add “oTrans.Refresh();” to “SaveUD01Record()” method to refresh the GUI after Update the SRepQDtl.QuotaAmt through Post-Processing BPM.

The delete button doesn’t work in UD01 Table entry.

// **************************************************
// Custom code for SalesRepQuotaForm
// Created: 2/1/2021 9:53:06 AM
// **************************************************
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 UD01Adapter _ud01Adapter;
	private EpiDataView _edvSRepQDtl;
	private DataTable UD01_Column;
	private EpiDataView _edvUD01;
	private string _Key1UD01;
	private string _Key2UD01;
	private string _Key3UD01;
	private string _Key4UD01;
	private string _Key5UD01;
	private DataView SRepQDtl_DataView;
	// 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

		InitializeUD01Adapter();
		this._Key1UD01 = string.Empty;
		this._Key2UD01 = string.Empty;
		this._Key3UD01 = string.Empty;
		this._Key4UD01 = string.Empty;
		this._Key5UD01 = string.Empty;
		this.baseToolbarsManager.ToolClick += new Infragistics.Win.UltraWinToolbars.ToolClickEventHandler(this.baseToolbarsManager_ToolClickForUD01);
		this.SalesRepQuotaForm.BeforeToolClick += new Ice.Lib.Framework.BeforeToolClickEventHandler(this.SalesRepQuotaForm_BeforeToolClickForUD01);
		this.SalesRepQuotaForm.AfterToolClick += new Ice.Lib.Framework.AfterToolClickEventHandler(this.SalesRepQuotaForm_AfterToolClickForUD01);
		this.SRepQDtl_Row.EpiRowChanged += new EpiRowChanged(this.SRepQDtl_AfterRowChangeForUD01);
		this.SRepQDtl_DataView = this.SRepQDtl_Row.dataView;
		this.SRepQDtl_DataView.ListChanged += new ListChangedEventHandler(this.SRepQDtl_DataView_ListChangedForUD01);
		this.SRepQDtl_Row.BeforeResetDataView += new Ice.Lib.Framework.EpiDataView.BeforeResetDataViewDelegate(this.SRepQDtl_BeforeResetDataViewForUD01);
		this.SRepQDtl_Row.AfterResetDataView += new Ice.Lib.Framework.EpiDataView.AfterResetDataViewDelegate(this.SRepQDtl_AfterResetDataViewForUD01);
		// 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

		if ((this._ud01Adapter != null))
		{
			this._ud01Adapter.Dispose();
			this._ud01Adapter = null;
		}
		this._edvUD01 = null;
		this._edvSRepQDtl = null;
		this.UD01_Column = null;
		this._Key1UD01 = null;
		this._Key2UD01 = null;
		this._Key3UD01 = null;
		this._Key4UD01 = null;
		this._Key5UD01 = null;
		this.baseToolbarsManager.ToolClick -= new Infragistics.Win.UltraWinToolbars.ToolClickEventHandler(this.baseToolbarsManager_ToolClickForUD01);
		this.SalesRepQuotaForm.BeforeToolClick -= new Ice.Lib.Framework.BeforeToolClickEventHandler(this.SalesRepQuotaForm_BeforeToolClickForUD01);
		this.SalesRepQuotaForm.AfterToolClick -= new Ice.Lib.Framework.AfterToolClickEventHandler(this.SalesRepQuotaForm_AfterToolClickForUD01);
		this.SRepQDtl_Row.EpiRowChanged -= new EpiRowChanged(this.SRepQDtl_AfterRowChangeForUD01);
		this.SRepQDtl_DataView.ListChanged -= new ListChangedEventHandler(this.SRepQDtl_DataView_ListChangedForUD01);
		this.SRepQDtl_DataView = null;
		this.SRepQDtl_Row.BeforeResetDataView -= new Ice.Lib.Framework.EpiDataView.BeforeResetDataViewDelegate(this.SRepQDtl_BeforeResetDataViewForUD01);
		this.SRepQDtl_Row.AfterResetDataView -= new Ice.Lib.Framework.EpiDataView.AfterResetDataViewDelegate(this.SRepQDtl_AfterResetDataViewForUD01);
		// End Wizard Added Object Disposal

		// Begin Custom Code Disposal

		// End Custom Code Disposal
	}

	private void InitializeUD01Adapter()
	{
		// Create an instance of the Adapter.
		this._ud01Adapter = new UD01Adapter(this.oTrans);
		this._ud01Adapter.BOConnect();

		// Add Adapter Table to List of Views
		// This allows you to bind controls to the custom UD Table
		this._edvUD01 = new EpiDataView();
		this._edvUD01.dataView = new DataView(this._ud01Adapter.UD01Data.UD01);
		this._edvUD01.AddEnabled = true;
		this._edvUD01.AddText = "New UD01";
		if ((this.oTrans.EpiDataViews.ContainsKey("UD01View") == false))
		{
			this.oTrans.Add("UD01View", this._edvUD01);
		}

		// Initialize DataTable variable
		this.UD01_Column = this._ud01Adapter.UD01Data.UD01;

		// Initialize EpiDataView field.
		this._edvSRepQDtl = ((EpiDataView)(this.oTrans.EpiDataViews["SRepQDtl"]));

		// Set the parent view / keys for UD child view
		string[] parentKeyFields = new string[4];
		string[] childKeyFields = new string[4];
		parentKeyFields[0] = "SalesRepCode";
		childKeyFields[0] = "Key1";
		parentKeyFields[1] = "FiscalCalendarID";
		childKeyFields[1] = "Key2";
		parentKeyFields[2] = "FiscalYear";
		childKeyFields[2] = "Key3";
		parentKeyFields[3] = "FiscalPeriod";
		childKeyFields[3] = "Key4";
		this._edvUD01.SetParentView(this._edvSRepQDtl, parentKeyFields, childKeyFields);

		if ((this.oTrans.PrimaryAdapter != null))
		{
			// this.oTrans.PrimaryAdapter.GetCurrentDataSet(Ice.Lib.Searches.DataSetMode.RowsDataSet).Tables.Add(this._edvUD01.dataView.Table.Clone())
		}

	}

	private void GetUD01Data(string key1, string key2, string key3, string key4, string key5)
	{
		if ((this._Key1UD01 != key1) || (this._Key2UD01 != key2) || (this._Key3UD01 != key3) || (this._Key4UD01 != key4) || (this._Key5UD01 != key5))
		{
			// Build where clause for search.
			string whereClause = "Key1 = \'" + key1 + "\' And Key2 = \'" + key2 + "\' And Key3 = \'" + key3 + "\' And Key4 = \'" + key4 + "\'";
			System.Collections.Hashtable whereClauses = new System.Collections.Hashtable(1);
			whereClauses.Add("UD01", whereClause);

			// Call the adapter search.
			SearchOptions searchOptions = SearchOptions.CreateRuntimeSearch(whereClauses, DataSetMode.RowsDataSet);
			this._ud01Adapter.InvokeSearch(searchOptions);

			if ((this._ud01Adapter.UD01Data.UD01.Rows.Count > 0))
			{
				this._edvUD01.Row = 0;
			} else
			{
				this._edvUD01.Row = -1;
			}

			// Notify that data was updated.
			this._edvUD01.Notify(new EpiNotifyArgs(this.oTrans, this._edvUD01.Row, this._edvUD01.Column));

			// Set key fields to their new values.
			this._Key1UD01 = key1;
			this._Key2UD01 = key2;
			this._Key3UD01 = key3;
			this._Key4UD01 = key4;
			this._Key5UD01 = key5;
		}
	}

	private void GetNewUD01Record()
	{
		DataRow parentViewRow = this._edvSRepQDtl.CurrentDataRow;
		// Check for existence of Parent Row.
		if ((parentViewRow == null))
		{
			return;
		}
		if (this._ud01Adapter.GetaNewUD01())
		{
			string salesrepcode = parentViewRow["SalesRepCode"].ToString();
			string fiscalcalendarid = parentViewRow["FiscalCalendarID"].ToString();
			string fiscalyear = parentViewRow["FiscalYear"].ToString();
			string fiscalperiod = parentViewRow["FiscalPeriod"].ToString();

			// Get unique row count id for Key5
			int rowCount = this._ud01Adapter.UD01Data.UD01.Rows.Count;
			int lineNum = rowCount;
			bool goodIndex = false;
			while ((goodIndex == false))
			{
				// Check to see if index exists
				DataRow[] matchingRows = this._ud01Adapter.UD01Data.UD01.Select("Key5 = \'" + lineNum.ToString() + "\'");
				if ((matchingRows.Length > 0))
				{
					lineNum = (lineNum + 1);
				} else
				{
					goodIndex = true;
				}
			}

			// Set initial UD Key values
			DataRow editRow = this._ud01Adapter.UD01Data.UD01.Rows[(rowCount - 1)];
			editRow.BeginEdit();
			editRow["Key1"] = salesrepcode;
			editRow["Key2"] = fiscalcalendarid;
			editRow["Key3"] = fiscalyear;
			editRow["Key4"] = fiscalperiod;
			editRow["Key5"] = lineNum.ToString();
			editRow.EndEdit();

			// Notify that data was updated.
			this._edvUD01.Notify(new EpiNotifyArgs(this.oTrans, (rowCount - 1), this._edvUD01.Column));
		}
	}

	private void SaveUD01Record()
	{
		// Save adapter data
		this._ud01Adapter.Update();
		//oTrans.Refresh(); // Used to update the control SRepQDtl.QuotaAmt in "Product Group Quota" Sheet
	}

	private void DeleteUD01Record()
	{
		// Check to see if deleted view is ancestor view
		bool isAncestorView = false;
		Ice.Lib.Framework.EpiDataView parView = this._edvUD01.ParentView;
		while ((parView != null))
		{
			if ((this.oTrans.LastView == parView))
			{
				isAncestorView = true;
				break;
			} else
			{
				parView = parView.ParentView;
			}
		}

		// If Ancestor View then delete all child rows
		if (isAncestorView)
		{
			DataRow[] drsDeleted = this._ud01Adapter.UD01Data.UD01.Select("Key1 = \'" + this._Key1UD01 + "\' AND Key2 = \'" + this._Key2UD01 + "\' AND Key3 = \'" + this._Key3UD01 + "\' AND Key4 = \'" + this._Key4UD01 + "\'");
			for (int i = 0; (i < drsDeleted.Length); i = (i + 1))
			{
				this._ud01Adapter.Delete(drsDeleted[i]);
			}
		} else
		{
			if ((this.oTrans.LastView == this._edvUD01))
			{
				if ((this._edvUD01.Row >= 0))
				{
					DataRow drDeleted = ((DataRow)(this._ud01Adapter.UD01Data.UD01.Rows[this._edvUD01.Row]));
					if ((drDeleted != null))
					{
						if (this._ud01Adapter.Delete(drDeleted))
						{
							if ((_edvUD01.Row > 0))
							{
								_edvUD01.Row = (_edvUD01.Row - 1);
							}

							// Notify that data was updated.
							this._edvUD01.Notify(new EpiNotifyArgs(this.oTrans, this._edvUD01.Row, this._edvUD01.Column));
						}
					}
				}
			}
		}
	}

	private void UndoUD01Changes()
	{
		this._ud01Adapter.UD01Data.RejectChanges();

		// Notify that data was updated.
		this._edvUD01.Notify(new EpiNotifyArgs(this.oTrans, this._edvUD01.Row, this._edvUD01.Column));
	}

	private void ClearUD01Data()
	{
		this._Key1UD01 = string.Empty;
		this._Key2UD01 = string.Empty;
		this._Key3UD01 = string.Empty;
		this._Key4UD01 = string.Empty;
		this._Key5UD01 = string.Empty;

		this._ud01Adapter.UD01Data.Clear();

		// Notify that data was updated.
		this._edvUD01.Notify(new EpiNotifyArgs(this.oTrans, this._edvUD01.Row, this._edvUD01.Column));
	}

	private void baseToolbarsManager_ToolClickForUD01(object sender, Infragistics.Win.UltraWinToolbars.ToolClickEventArgs args)
	{
		// EpiMessageBox.Show(args.Tool.Key);
		switch (args.Tool.Key)
		{
			case "EpiAddNewNew UD01":
				GetNewUD01Record();
				break;

			case "ClearTool":
				ClearUD01Data();
				break;

			case "UndoTool":
				UndoUD01Changes();
				break;
/*
			case "Update": // Delete this one! 
			oTrans.Refresh();
			break;
*/
		}
	}

	private void SalesRepQuotaForm_BeforeToolClickForUD01(object sender, Ice.Lib.Framework.BeforeToolClickEventArgs args)
	{
		// EpiMessageBox.Show(args.Tool.Key);
		switch (args.Tool.Key)
		{
			case "SaveTool":
				SaveUD01Record();
				break;
		}
		//EpiMessageBox.Show(args.Tool.Key);
	}

	private void SalesRepQuotaForm_AfterToolClickForUD01(object sender, Ice.Lib.Framework.AfterToolClickEventArgs args)
	{
		// EpiMessageBox.Show(args.Tool.Key);
		switch (args.Tool.Key)
		{
			case "DeleteTool":
				if ((args.Cancelled == false))
				{
					DeleteUD01Record();
				}
				break;
		}
	}

	private void SRepQDtl_AfterRowChangeForUD01(EpiRowChangedArgs args)
	{
		// ** add AfterRowChange event handler
		string salesrepcode = args.CurrentView.dataView[args.CurrentRow]["SalesRepCode"].ToString();
		string fiscalcalendarid = args.CurrentView.dataView[args.CurrentRow]["FiscalCalendarID"].ToString();
		string fiscalyear = args.CurrentView.dataView[args.CurrentRow]["FiscalYear"].ToString();
		string fiscalperiod = args.CurrentView.dataView[args.CurrentRow]["FiscalPeriod"].ToString();
		GetUD01Data(salesrepcode, fiscalcalendarid, fiscalyear, fiscalperiod, string.Empty);
	}

	private void SRepQDtl_DataView_ListChangedForUD01(object sender, ListChangedEventArgs args)
	{
		// ** add ListChanged event handler
		string salesrepcode = SRepQDtl_DataView[0]["SalesRepCode"].ToString();
		string fiscalcalendarid = SRepQDtl_DataView[0]["FiscalCalendarID"].ToString();
		string fiscalyear = SRepQDtl_DataView[0]["FiscalYear"].ToString();
		string fiscalperiod = SRepQDtl_DataView[0]["FiscalPeriod"].ToString();
		GetUD01Data(salesrepcode, fiscalcalendarid, fiscalyear, fiscalperiod, string.Empty);
	}

	private void SRepQDtl_BeforeResetDataViewForUD01(object sender, EventArgs args)
	{
		// ** remove ListChanged event handler
		this.SRepQDtl_DataView.ListChanged -= new ListChangedEventHandler(this.SRepQDtl_DataView_ListChangedForUD01);
	}

	private void SRepQDtl_AfterResetDataViewForUD01(object sender, EventArgs args)
	{
		// ** reassign DataView and add ListChanged event handler
		this.SRepQDtl_DataView = this.SRepQDtl_Row.dataView;
		this.SRepQDtl_DataView.ListChanged += new ListChangedEventHandler(this.SRepQDtl_DataView_ListChangedForUD01);
	}
}

The UD01 fields are populated correctly in the DB, this is my mapping fields:

if I join the UD01 table with ERP.SRepQDtl it works fine:

I’m looking at your gif again. So is the issue with the refresh, you’re not seeing the associated data? i.e. if you re-select the salesperson, fiscal year and period, is the data added still there?

To debug, I’d add some MessageBox.Show to spit out the keys in both GetUD01Data and GetNewUD01Record to make sure there isn’t something weird going on there.

It is correct, if I return to Fiscal Period Detail sheet and select another period, and then select the period recently modified and go to Product Group Quota Sheet, the data is there. So you see nothing wrong with the code?

I would be adding the following to the top of the GetUD01Data method to see when it’s firing:
MessageBox.Show(“GetUD01Data Key1: '”+key1+"'Key2: '"+key2+"'Key3: '"+key3+"'Key4: '"+key4+"'Key5: ‘"+key5+"’");

1 Like

Where is the logic that populates the SRepQDtl.QuotaAmt?
Is that a BPM or in the customization? It should likely be a BPM.

Jason Woods
http://LinkedIn.com/in/jasoncwoods

Wow, very usefull a simple MessageBox to debug!! :open_mouth:

Check this: In Period Fiscal 1, when press the refresh button doesn’t bring up the MessageBox, but with any other it always shows the same information: (Key1 = ‘AARON’ And Key2 = ‘Main’ And Key3 = ‘2021’ And Key4 = ‘1’ And Key5 = ‘’), thats the problem! But, how to fix it? :thinking:

Thats correct, I use a BPM to update the SRepQDtl.QuotaAmt field by sum all Product Group Quota related to the Fiscal Period.

Where is the BPM located and what is your code?

The problem is not related to the BPMs, cause the refresh button still fail even with the BPMs turns off. I share whole solutionCstmSalesperson_Customer Solution_3.2.600.0.cab (86.4 KB) if you want to review the BPM’s code.