Determine which forms have a control bound to a specific DB field

Since you cannot delete a Part Class once it has been referenced, I needed a way to set Part Classes as “inactive”, so they would not be used in the future.

I did this by adding a boolean UD field “AllowUsage_c” to the PartClass table, and customized the Part Class Entry screen, to add a checkbox for that UD field. Then Customized the Part Entry form, adding filters to the Part Class dropdown control to remove PartClasses whose AllowUsage field is not set. This doesn’t really prevent it from being assigned (I’ll make a BPM later for that), but prevents people from selecting here.

So my question is… How can I find out which forms the Part Class can be selected on? So that I can customize those to do the same filtering trick I did on Part Maintenance.

I know it is also on the PO Entry form. I don’t mind if it is selectable as a search/filter criteria (like on the Stock Status Report). I just don’t want someone to select it to be used for a record like Part or PODetail.

One all-encompassing way of doing this is a BPM on GetList. You can set the whereClause to what you like, then what gets returned to any dropdown control anywhere is already filtered. We do the same thing in a couple of places.

2 Likes

I’ve not done a BPM on a GetList method.

Is it straightforward? Should it be Pre or Post?

Can it be context sensitive? I might want some Part Classes hidden from the Part Entry, but be allowed on the PO Detail.

It’s VERY straightforward, though introducing context sensitivity might make for a bit of complication.

All we do is add a pre directive and manipulate the “whereClause” variable, which is a built-in one and acts exactly like the SearchFilter in form customization. For future-proofing it’s a good idea to assume there might be something already in there, otherwise it’s one widget to set to what you like. I assume you could test for something in a conditional as usual if you wanted to vary it - we haven’t needed to so far.

One other workaround is that I think it doesn’t apply if you set the dropdown to GetRows instead of GetList, so you could possibly do that in any forms where you wanted the whole lot.

2 Likes

You can use callContextClient.AssemblyName to exclude a certain program from having the Part Class filtered.

2 Likes

If I recall correctly, specifying the filters on a Form control required one filter per line and they would all be ANDed together.

I have it working with the one filter (same as used in the customized form)

image

What’s the format/syntax for multiple filters in the BPM?

"(PartClass.AllowUsage_c=TRUE) AND (PartClass.ClassID <> \"SHSP\")"

Or

"(PartClass.AllowUsage_c=TRUE) \n (PartClass.ClassID <> \"SHSP\")"

We use the “AND” form, as per the form SearchFilter field rather than the filter list. And single quotes within the overall double-quoted string. Basically a SQL “where” as a string expression.

Setting the WhereClause (using a Set Argument/Variable widget) to:

"(PartClass.AllowUsage_c = TRUE)"

works as expected. Only Part Classes with that UD field set are returned.

.
While setting it to

"(PartClass.ClassID = 'BFIL')"

passes the syntax check and the BPM can be saved. But initiating a GetList yields the error:

Error accessing the database: 
The multi-part identifier "PartClass.ClassID" could not be bound.

Details show

Server Side Exception

Error accessing the database: The multi-part identifier "PartClass.ClassID" could not be bound.

Exception caught in: Epicor.ServiceModel

Error Detail 
============
Description:  Error accessing the database: The multi-part identifier "PartClass.ClassID" could not be bound.
Program:  System.Data.dll
Method:  OnError
Original Exception Type:  SqlException
SQL Line Number:  9
SQL Error Number:  4104

What am I overlooking?

We only use the field name itself, as

"InActive_c = false and (" + whereClause + ")"

but I’m always cautious about saying we’re doing anything the correct way … worth a try, though?

1 Like

Using just the field name worked.

But another question… Your example looks like it is adding the original whereClause, with the
... AND (" + whereClause + ")"

Won’t that error out if the original whereClause from the calling form is blank?

Yes - but in case anyone does put anything in the whereClause and wonders why it doesn’t do anything, there’s a conditional checking if it’s blank or not. If it isn’t, it does this. I could have shown the other one, but it didn’t have an “AND” in it.

1 Like

I added the Cll Context AssemblyName to an information dialog, but it is blank (in both the pre-and post proc directives)

Pre-Proc

image

Post-Proc

image

Do I have to determine it in code?

@ckrusen I see this turned out to be an XY problem, but did you ever find a solution to your original question? I’m thinking about cleaning up some unused UD columns. I know how to search for references in BPMs, but not in UI customizations.

Couldn’t answer my original question about finding references in all forms…

But if you are only interested in Customizations, make a BAQ on table XXXDef and search the field Content.

Ah, yes. I’ve still got the old XXXChunk.

select
	concat(Key2, '_', Key1) 'File',
	Chunk
from Ice.XXXChunk
where TypeCode = 'Customization'

Save as CSV, then

cat customizations.csv | while IFS=','; read -ra line; do echo ${line[0]}; echo -n ${line[1]} | base64 -d -i | bunzip2 > Decoded/${line[0]}.xml; done

Then grep ftw.

1 Like