0

I would like to customize the SOLine InventoryID selector to filter out certain inventory items based on the value of the class they are part of. I've read about the [PXRestrictor] attribute and how it can be used to filter selectors. This seems like it would work, except that the Item Class name is not available in that DAC, so I tried this:

[PXRestrictor(typeof(SelectFrom<InventoryItem>.
    InnerJoin<INItemClass>.On<INItemClass.itemClassID.IsEqual<InventoryItem.itemClassID>>.
    Where<INItemClass.itemClassCD.IsEqual<itemClassValue>>), "Custom items")]

but this is apparently not allowed.

It seems like I would need to override the selector itself, but the existing selector is rather convoluted and hidden beneath layers of attributes and I am not sure how to replicate even that, not to mention that option seeming rather near-sighted.

How could I go about this, or is this simply not a good option?

Deetz
  • 329
  • 1
  • 16

1 Answers1

2

PXRestrictor is used with a where clause to specify how to restrict.

[PXRestrictor(typeof(
    Where<Current<InventoryItem.itemClassID>, Equal<itemClassValue>>
    ), "Custom Items")]

In the example above, itemClassValue must be a type of the classID.

You can Merge with current attributes on the field where the selector is defined as a DAC extension if it needs to exist everywhere or with CacheAttached if only within a specific graph.

Update

As you indicated that you need to allow an entire tree of item classes in the comments, you might try this approach which worked for me in a case where I needed to only allow certain values on a condition.

Add a PXInt field onto SOLine for your BASE item class. Use the RowSelecting event to set it, and then use it in your restrictor.

Sample Base Item Class ID field:

#region BaseItemClassID
[PXInt]
public virtual int? BaseItemClassID { get; set; }
public abstract class baseItemClassID : PX.Data.BQL.BqlInt.Field<baseItemClassID> { }
#endregion

Restrictor to use in CacheAttached to limit to only items of your base item class:

[PXRestrictor(typeof(Where<InventoryItem.baseItemClassID, Equal<myBaseItemClassType>>), "")]

If this is applied to all SOLine records, you will need to add your "when to allow only my specific item class tree" to the restrictor. Remember that the restrictor must return True to give results, so it might need to be "Where NOT my condition OR BaseItemClassID == myBaseItemClassID".

In my case, I needed a simple condition to allow using standard locations where I have some locations configured as special use for segregating certain inventory. I just set a PXBool field to true when I want to allow use of standard locations, and the restrictor flips the allowed selection. I think this concept might work in your case as well as outlined above.

Brian Stevens
  • 1,826
  • 1
  • 7
  • 16
  • Right, I understand, but if I can't do a join, ``itemClassCD`` is not available, and ``itemClassID`` expects an ``int``. I'm trying to match against a ``StartsWith`` function of some sort because I have a bunch of segmented classes that start the same way and should all be excluded. Probably should've specified that. – Deetz Oct 28 '20 at 19:20
  • I think you are making it too complicated. If you know the ItemClassCD, then you know the ItemClassID. The Equal must be either a type of a constant containing the value or a Current to retrieve it from somewhere. The selector should for InventoryID should be looking up to InventoryItem already, so you are restricting to itemClassID on InventoryItem rather than SOLine. If you need it to be variable, you could make a view for INItemClass and instead of itemClassValue as a constant, you can use Current of INItemClass.itemClassID. – Brian Stevens Oct 28 '20 at 19:27
  • You may be right. I managed to get this working for a single (1) item class. However, this still doesn't solve my issue of also wanting to include all child-item classes. Do you have a solution for that? – Deetz Oct 28 '20 at 20:26
  • That certainly is a bit more complicated. I'm not sure how I would approach that. I have been working all afternoon on getting a set of PXRestrictor attributes to limit a location list based on different conditions and noticed the syntax issue of your original post. – Brian Stevens Oct 28 '20 at 20:36
  • Would it be possible to check against an array of ``ItemClassID`` or something? – Deetz Oct 28 '20 at 20:37
  • Not sure. I have yet to need to get super sophisticated with PXRestrictor. What I have seen in source code is that the complex issues tend to be written in their own attributes where BQL is employed to further adjust the results. – Brian Stevens Oct 28 '20 at 20:39
  • You CAN do a lot of OR's in the Where clause if your list is finite. – Brian Stevens Oct 28 '20 at 20:40
  • I tried to replicate their attribute extensions, but it always complains that I must define a body because it's not marked as abstract or extern. I feel like I must be missing something. – Deetz Oct 28 '20 at 20:43
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/223785/discussion-between-brian-stevens-and-deetz). – Brian Stevens Oct 28 '20 at 21:34
  • Found a possible solution to your additional need. Updating answer. – Brian Stevens Oct 30 '20 at 11:59
  • Now that is creative thinking. – Deetz Oct 30 '20 at 12:53