UD Fields Forced Read Only When Engineered Checkbox is Selected

Hello all, I am having an issue where the textbox I have linked to a UD field is being forced to be read only. The field is only locked when the Engineered checkbox is checked.

After a bit of looking I found that everything on JobHead locks when this checkbox is selected.
However, this field is on a separate UD table so I’m confused as to why it’s being set to read only as well. Is there any way to force a single UD field to be not read only when Engineered is selected?

Also It is to my understanding that it is probably possible to “fix” this in company configuration by allowing changes on engineered jobs. We need to keep prevent changes on, I just need this one field to be able to be edited by the users.

Thanks in advance if anyone has any clever ideas

Like a UDxx table? Or JobHead_UD table?

Its on Jobhead_UD. I assume that is probably the problem point?

1 Like

Yes. The UD fields come in with the dataview, and are treated as part of the original table.

There are a few places in E10 where a header field is still accessible even when the header is “locked”. For example, the Tracking number field of a ShipHead record is still accessible even after the packer is marked shipped (which sets all other ShipHead related fields to read only).

Have you tried the Extended properties wizard in the customization?

Yeah I was poking around there the other day and I set readonly to false. However, it seems like that either doesn’t work or it doesn’t stick.

Yeah I just tried a few things I though would work, and none did …

I guess I’ll have to put the bat-signal out for @josecgomez

How does one enable a UD field in a “locked” dataview on a form?

Like if I had OrderHed.Notes_c field on the Order Entry form. As soon as the Order is closed, that control becomes disabled and/or read only. Want to be ablt to change the Notes_c field of a closed order.

Or does the order being closed prevent any changes to the OrderHed DB record?

BAHAHAHA… @ckrusen I’m trying to do that myself on a different form with @Banderson and… let me tell you we went down the deepst rabbit hole and have yet to be successful…

You could try this (which works on Posted Invoice Update)
So the gist of the below is look at all the RowRules in the DataView, find the one which disables everything, update the “except” array to include the custom fields you want.

private void fixupDisableRowOnPostedInvoice()
	{
        SortedList rowRules = (SortedList) GetInstanceField(InvcHead_Row.GetType(), InvcHead_Row, "myRowRules");
        if (rowRules != null)
        {
			foreach (RowRule rr in rowRules.Values)
			{
            	//RowRule rr = (RowRule)rowRules[43];
				string arg1 = rr.Arg1 as string;
				string arg2 = rr.Arg2 as string;
				if (!string.IsNullOrEmpty(arg1) && string.Compare(arg1, "RowMod", true) == 0 && 
					rr.Condition == Ice.Lib.ExtendedProps.RuleCondition.NotEqual && 
					!string.IsNullOrEmpty(arg2) && string.Compare(arg2, "ALWAYS", true) == 0)
				{
					// we have our row rule
					foreach (RuleAction ra in rr.Actions.Values)
					{
						string epiBinding = (string) GetInstanceField(ra.GetType(), ra, "epiBinding");
						if (!string.IsNullOrEmpty(epiBinding) && 
							string.Compare(epiBinding, "InvcHead.all", true) == 0)
						{
							// we have our rule action (to disable all columns except for the few)
							Ice.Lib.ExtendedProps.DisableRowAction dra = (Ice.Lib.ExtendedProps.DisableRowAction) ra;
							if (dra != null)
							{
								string[] notThese = (string[]) GetInstanceField(dra.GetType(), dra, "notThese");
								if (notThese != null)
								{
									Array.Resize(ref notThese, notThese.Length + 2);
									notThese[notThese.Length - 2] = "sgcOverPayment_c";
									notThese[notThese.Length - 1] = "sgcOverPaymentDate_c";
									SetInstanceField(dra.GetType(), dra, "notThese", notThese);
								}
							}
						}
					}
				}
			}
        }
	}

internal static object GetInstanceField(Type type, object instance, string fieldName)
    {
        BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
            | BindingFlags.Static;
        FieldInfo field = type.GetField(fieldName, bindFlags);
		if (field != null)
        	return field.GetValue(instance);
		return null;
    }
    internal static void SetInstanceField(Type type, object instance, string fieldName, object value)
    {
        BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
            | BindingFlags.Static;
        FieldInfo field = type.GetField(fieldName, bindFlags);
		if (field != null)
        	field.SetValue(instance, value);
    }

@josecgomez did this work, in Notify Event?

ControlSettings cs = new ControlSettings();
cs.IsEnabled = true;
cs.IsReadOnly = false;
 
view.SetCurrentRowPropertyManually("EmailJT_c", cs);
view.SetCurrentRowProperty("EmailJT_c", cs);

Nope

So this worked for me on JobHead

2 Likes

The one we were struggling with was on quote @hkeric.wci

Custom UD field (don’t want read only) after quote is marked quoted.

See if one of your RowRule tricks works there we tried a few of those too with no success.

I have to check, which one of this worked on Quote Entry, I do have one… That’s where I found out about the SetRowProperty, back in 10.1.400 – not sure if it still works in 10.2.600… Not even sure if it was the control or RowProp…

Didn’t try Rowrules back then

2 Likes

Tried it on a UD field of OrderHed, when Order is closed, and it does not work.

That works! @hkeric.wci you’re an actual legend thanks for the fix.

Almost exactly opposite of my post to set as read only :smiley:… Nice one! Wish I had that code a month ago :sweat_smile:

You can set a field read-only or read-write via the DataColumn’s extended properties (this is how the EpiDataView controls it internally)

edvJobHead.dataView.Table.Columns["SomeField"].ExtendedProperties["ReadOnly"] = false;

So I tried this again @hkeric.wci, and it still didn’t work. Does this work for you on a quote form? There are some CSG customizations that are in there, so I don’t know if that’s affecting us or not.

@Banderson Similar code to the above works for me on 10.2.400.9 on Opportunity / Quote Form:

	// This Epi View Notification is for catching any new/updated records in the PriceBreak (QuotyQty) grid
	private void edvQuoteQty_EpiViewNotification(EpiDataView view, EpiNotifyArgs args)
		{
		// React to updates on the PriceBreak table and ensure it is ReadOnly if Configured Part
		// ** 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
		// Next line commented as I want to react to changes in this grid.
		// if ((args.NotifyType == EpiTransaction.NotifyType.AddRow)) // Always do this :)
			{
			if ((args.Row > -1))
				{
				try {
					SetRoForUnitsAndPrice((Convert.ToString(txtIsConfiguredPart.Value)=="On"?true:false));
					this.txtIsConfiguredPart.Visible = false;  // Keep my config part field hidden during view updates
					}
				catch (System.Exception ex)
					{
					ExceptionBox.Show(ex);
					}
				}
			}
		}

		// This is to catch new Quotes and set the Default Event value
		// ** 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.Initialize) || (args.NotifyType==EpiTransaction.NotifyType.AddRow))
			{
			if ((args.Row > -1))
				{
				if (Convert.ToString(edvQuoteHed.dataView[edvQuoteHed.Row]["MktgEvntSeq"])=="0") 
					{
					edvQuoteHed.dataView[edvQuoteHed.Row]["MktgEvntSeq"]=1;
					edvQuoteHed.Notify(new EpiNotifyArgs(oTrans,edvQuoteHed.Row,edvQuoteHed.Column));
					}
				this.txtIsConfiguredPart.Visible = false;  // Keep my config part field hidden during view updates
				}
			}
		}

	private void SetRoForUnitsAndPrice(bool bIsConfigured)
		{
		// This method takes the arrray { bypassGroups } defined above checked against user's security groups.
		bool bReadOnly = true;
		if ((bAuthedBypass(bypassGroups)) || (!bIsConfigured )) bReadOnly=false; 
		// Columns to set RO when part is configured
		string[] aQuoteDtlCols = { "OrderUnitPrice" 
									, "ExpUnitPrice" 
									, "DocExpUnitPrice" 
									, "InExpUnitPrice" 
									, "DspExpUnitPrice" 
									, "DocInExpUnitPrice" 
									, "DocDspExpUnitPrice" };
		string sEugQuoteQtys = "b4888395-8a78-4e5b-bd43-63b324f1f4b5";  // Guid for eug QuoteQty
		foreach (string ugCol in aQuoteDtlCols) 
			{ if (edvQuoteDtl.dataView.Table.Columns.Contains(ugCol))
				{
				edvQuoteDtl.dataView.Table.Columns[ugCol].ExtendedProperties["ReadOnly"]=bReadOnly;
				}
			}
         ((EpiUltraGrid)csm.GetNativeControlReference(sEugQuoteQtys)).ReadOnly=bReadOnly;
		}

@Banderson so it works fine in 10.1 but in 10.2 its a bit diff hm…

The only thing that seems to be doing the trick for me in 10.2.600 is:

// In EpiViewNotification Event
cmbQuoteStatus.Enabled = true;
cmbQuoteStatus.IsEpiReadOnly = false;
cmbQuoteStatus.ReadOnly = false;

The Quoted Date Fields you could debug, those are Epicor fields and see how they mark them avail when Quoted = true
image

But id like to see if I can make a RowRule with a custom condition and check for, but the problem might be that Epicor themselves are not using RowRules but just the helper to disable all controls…

Ideally something like this id like to see, i’ll need to poke around.

bool QuoteHed_CustomRuleCondition(Ice.Lib.ExtendedProps.RowRuleDelegateArgs args)
{
  // oTrans does have this
  return oTrans.QuotedAndPreventQQChange;
}

@josecgomez remember how you set a Custom Color… Epicor also lets you set state of the control, I did this on a dashboard I need to find it where the entire Row was disabled, but certain columns were enabled. #foodforthought

ControlSettings customColor = new ControlSettings();
customColor.IsEnabled = true;
customColor.IsReadOnly = false;
customColor.OverrideControlState = ControlSettings.OverrideState.Enabled;

There is a ExtendedProps Method which may be used

public static void SetCurrentProps(IEpiBoundControl oCtrl, ControlSettings Props, bool isSettingBackToStartupProps)

This did it. Thanks!