Ice.ZDataField.CodeDescriptionList

All right, so while trying to figure out what all of the available codes mean in Ice.Menu.OptionType and Ice.Menu.OptionSubType, since they were not all listed in the Data Dictionary Viewer, I found out that the available codes and descriptions for these fields—and every other field like them that use a seemingly hard-coded list of values and descriptions such as Customer.EntityUseCode, Customer.CustomerType, InvcHead.InvoiceType, OrderHed.PayFlag, and many many more fields in both the ERP and ICE namespaces—live in the ZDataField.CodeDescriptionList column of the row corresponding to the DataTable field we’re dealing with.

I couldn’t figure out how to split the CodeDescriptionList (nvarchar) into a two-dimensional array in the query of my updatable BAQ, so I ended up retrieving the CodeDescriptionList for the fields I wanted in a post-processing directive on the GetList method of the BAQ. The code is pretty straightforward:

// set up the CodeDesc lists
string[] OptionTypeCodes = (from zdfRow in Db.ZDataField where zdfRow.SystemCode == "ICE" && zdfRow.DataTableID == "Menu" && zdfRow.FieldName == "OptionType" select zdfRow.CodeDescriptionList).FirstOrDefault().Split('~');

string[] OptionSubTypeCodes = (from zdfRow in Db.ZDataField where zdfRow.SystemCode == "ICE" && zdfRow.DataTableID == "Menu" && zdfRow.FieldName == "OptionSubType" select zdfRow.CodeDescriptionList).FirstOrDefault().Split('~');

// loop through results table and replace codes with descriptions
foreach (var ttRow in result.Results)
{
  string thisOptionTypeCode = (from codeRow in OptionTypeCodes where codeRow.StartsWith(ttRow["Menu_OptionType"].ToString() + '`') select (codeRow != null ? codeRow.Split('`')[1] : "")).FirstOrDefault();
  if (!String.IsNullOrEmpty(thisOptionTypeCode)) ttRow["Menu_OptionType"] = thisOptionTypeCode;
  
  string thisOptionSubTypeCode = (from codeRow in OptionSubTypeCodes where codeRow.StartsWith(ttRow["Menu_OptionSubType"].ToString() + '`') select (codeRow != null ? codeRow.Split('`')[1] : "")).FirstOrDefault();
  if (!String.IsNullOrEmpty(thisOptionSubTypeCode)) ttRow["Menu_OptionSubType"] = thisOptionSubTypeCode;
}

Works just fine, as you can see:

Now, naturally the vast majority of these CodeDescriptionLists are going to be used by special hidden logic everywhere in Epicor and shouldn’t be touched. But it got me wondering, if one were to make an updatable BAQ for ZDataFields, can anyone think of a use case for modifying these that won’t mess anything up?

Maybe removing unused options from the EntityUseCode fields, or changing/translating descriptions in certain fields, or maybe even adding new codes to existing fields with BPMs to use them. If I had known about this table/field when we were still first implementing Epicor and migrating from Exact Macola/Synergy, and if it was possible to do so, I might’ve changed the available options for Customer.CustomerType to match the five-category system we had been using: Suspect, Lead, End User, Customer, Reseller. Would it have been advisable to do so? Probably not but it seems like it would have made the data migration easier.

Any other thoughts about Ice.ZDataField.CodeDescriptionList?

I believe that this question falls under the answer “Don't do it man!” because you are likely to hurt yourself. The reason that these are locked down is because there is hard coded logic that uses the codes. For example, the Customer Type field has three options, and the software AUTOMATICALLY changes the customer from “Suspect” to “Prospect” to “Customer”. When you first create an entry, it defaults to Suspect (you can override)… when you create a quote, it automatically changes to Prospect. When you convert the quote, or enter an order, it will automatically convert to a customer type. Anything outside of those three options are likely to break something. Same goes for other fields such as the Make/Purchase codes in Parts, and other fix set values. They are fixed for a reason.
If the data if flexible, then there is a setup table to maintain that data.
So… Don’t Do it!

Epicor will also delete your changes on a Release Upgrade (and potentially on an Update) as the majority of the zData records are “Seed data” and they will be deleted and then replaced with the Upgrade to a new Release.
On thing that you can look at is using the in-built Translation capabilities. Those tools will allow you to change most strings in the system and those changes will persist Release over Release and we allow a new “translation” to be entered even for the base US English strings.