Skip to main content
Question

How to prevent selecting certain order numbers in Sales Order Entry using customization?

  • January 22, 2026
  • 8 replies
  • 43 views

I have tried different methods for this case. I could change the lookup using an attribute, but for manual entry and for the Prev/Next/Last buttons, it doesn’t work. When I write e.NewValue = null or e.Cancel, or throw some exception in FieldUpdating/FieldVerifying, in some cases it returns an error, but the record still gets displayed. I tried using a Current Document delegate to change and add restrictions and also wrote a restriction attribute, but these options didn’t work either.

8 replies

darylbowman
Captain II
Forum|alt.badge.img+16

The data view delegate would be the way to go, in my opinion. I believe you need to redefine the original data view in your extension as well as adding a data view delegate method. Did you do this?


Forum|alt.badge.img+2
  • Jr Varsity III
  • January 22, 2026

@mos11 ,
                  You can try using the FieldUpdated or RowSelected

        protected virtual void _(Events.FieldUpdated<SOOrder, SOOrder.orderNbr> e)
{
if (e.Row == null) return;

SOOrder order = e.Row;

// Define your blocking criteria here
if (ShouldBlockOrder(order))
{
// Clear the order number
e.Cache.SetValueExt<SOOrder.orderNbr>(e.Row, null);

// Show error message
throw new PXSetPropertyException(
"This order cannot be selected. Reason: [Your criteria]",
PXErrorLevel.Error);
}
}


protected virtual void _(Events.RowSelected<SOOrder> e)
{
if (e.Row == null) return;

SOOrder order = e.Row;

if (ShouldBlockOrder(order))
{
PXUIFieldAttribute.SetEnabled<SOOrder.orderNbr>(e.Cache, order, false);
e.Cache.RaiseExceptionHandling<SOOrder.orderNbr>(
order,
order.OrderNbr,
new PXSetPropertyException(
"This order is locked and cannot be modified.",
PXErrorLevel.Warning));
}
}

private bool ShouldBlockOrder(SOOrder order)
{

// Block by status
if (order.Status == SOOrderStatus.Completed ||
order.Status == SOOrderStatus.Cancelled)
{
return true;
}

// Block by custom field
SOOrderExt orderExt = order.GetExtension<SOOrderExt>();
if (orderExt?.UsrIsLocked == true)
{
return true;
}

// Block by date range
if (order.OrderDate < new DateTime(2024, 1, 1))
{
return true;
}

// Block specific order numbers
string[] blockedOrders = { "SO001234", "SO001235" };
if (Array.Exists(blockedOrders, element => element == order.OrderNbr))
{
return true;
}

return false;
}
}
}

event. If that doesn’t work, you can override the selector using  [PXMergeAttributes(Method = MergeMethod.Merge)].

I am attaching here sample code: 


  • Author
  • Freshman I
  • January 23, 2026

@darylbowman Thank you for your help. I tried this, but I don’t know exactly what I need to write. If I just do the same select as before and use continue for records I don’t need, it doesn’t work. Last, Next, and Prev also don’t work, and these records are not removed from the list.


  • Author
  • Freshman I
  • January 23, 2026

@noorula77 Thank you for your help. FieldUpdated and RowSelected events are too late for throwing an exception — at that moment the record has already been selected, and even after the error, the record is still selected. I have done many similar things on other fields that are not key fields, and there was no problem. But since this is a key field and I need to cancel the current record, I don’t know what to try.


Forum|alt.badge.img
  • Freshman I
  • January 23, 2026

To make Prev / Next / Last navigation skip restricted records, handling it in FieldVerifying / FieldUpdating is not sufficient. Those events only validate manual user entry and selector (lookup) selection, but navigation buttons change the current record in the primary view, so the restricted record can still be displayed.

 

The correct approach is to filter the primary view so restricted records are never returned by the view. This ensures the user cannot land on those records during navigation, and the records will not appear in the screen at all.

 

Perfect solution using a delegate (Primary View Filtering)

Example: Filter Base.Document view

protected IEnumerable document()

{

foreach (YourDAC row in Base.Document.Select())

{

// Skip restricted records so they never appear in the UI

if (IsRestricted(row))

continue;

 

yield return row;

}

}

 

private bool IsRestricted(YourDAC row)

{

// Example restriction condition

// Replace this with your actual business rule

return row.Status == "HOLD" || row.CustomerID == null;

}


Forum|alt.badge.img+2
  • Jr Varsity III
  • January 23, 2026

@mos11 ,
            You can try using RowSelecting event instead of RowSelected or you can try with overriding selector. This gives you defense in depth - users won't see the orders in lookups, but if they try to access them directly (via URL or API), the selection is blocked.
Example :

    [PXMergeAttributes(Method = MergeMethod.Merge)]

    [PXSelector(typeof(Search<SOOrder.orderNbr,

        Where<SOOrder.orderType, Equal<Current<SOOrder.orderType>>,

            And<SOOrder.status, NotEqual<SOOrderStatus.completed>,

            And<SOOrder.status, NotEqual<SOOrderStatus.cancelled>>>>>))]

    protected virtual void _(Events.CacheAttached<SOOrder.orderNbr> e) { }


  • Author
  • Freshman I
  • January 23, 2026

@noorula77 I created a selector attribute that works correctly, but it doesn’t solve my problem when the value is entered manually. I also have a problem with the Next, Prev, and Last buttons.


darylbowman
Captain II
Forum|alt.badge.img+16
  • January 23, 2026

If your data view delegate doesn't work, please post the code. Seems like all kinds of people are ready to help 😏