0
votes

I have ProductLine and ProductLineItem DACs. A Product Line contains a collection of related Inventory Items.

public class ProductLine : IBqlTable
{
    [PXDBIdentity()]
    public virtual int? LineID { get; set; }
    public abstract class lineID : IBqlField { }

    [PXDBString(50, IsKey = true)]
    [PXUIField(DisplayName = "Line ID")]
    [PXDefault]
    [PXSelector(typeof(ProductLine.lineCD),
        typeof(ProductLine.lineCD),
        typeof(ProductLine.description))]
    public virtual string LineCD { get; set; }
    public abstract class lineCD : IBqlField { }
    // ...
}

public class ProductLineItem : IBqlTable
{
    [PXDBInt(IsKey = true)]
    [PXDBDefault(typeof(ProductLine.lineID))]
    [PXParent(typeof(Select<ProductLine,
        Where<ProductLine.lineID,
            Equal<Current<ProductLineItem.lineID>>>>))]
    public virtual int? LineID { get; set; }
    public abstract class lineID : IBqlField { }

    [PXDBInt(IsKey = true)]
    [PXUIField(DisplayName = "Inventory ID")]
    [PXSelector(
        typeof(Search2<InventoryItem.inventoryID,
            LeftJoin<ProductLineItem,
                On<ProductLineItem.lineID, Equal<Current<ProductLineItem.lineID>>,
                    And<ProductLineItem.inventoryID, Equal<InventoryItem.inventoryID>>>>,
            Where<InventoryItem.itemStatus, Equal<InventoryItemStatus.active>,
                And<ProductLineItem.lineID, IsNull>>>),
        new Type[] {
            typeof(InventoryItem.inventoryCD),
            typeof(InventoryItem.descr)
        },
        SubstituteKey = typeof(InventoryItem.inventoryCD))]
    public virtual int? InventoryID { get; set; }
    public abstract class inventoryID : IBqlField { }
    // ...
}

These are then implemented in a very simple FormDetail entry page.

public class ProductLineEntry : PXGraph<ProductLineEntry, ProductLine>
{
    public PXSelect<ProductLine> ProductLines;
    public PXSelect<ProductLineItem,
        Where<ProductLineItem.lineID,
            Equal<Current<ProductLine.lineID>>>> ProductLineItems;
}

The PXSelector on the ProductLineItem.inventoryID provides active items not already added to the current Product Line. However, when the Selector is written like this attempting to Delete an item from the grid results in the red "x" indicator appearing but the record is never actually removed.

Changing the PXSelector to a more basic one without the Search2<>...

[PXSelector(typeof(InventoryItem.inventoryID),
    typeof(InventoryItem.inventoryCD),
    typeof(InventoryItem.descr),
    SubstituteKey = typeof(InventoryItem.inventoryCD))]

...the records delete normally.

How can I use a Search<> BQL in the Selector and still be able to delete records from the Details Grid?

1

1 Answers

1
votes

The problem takes place because of the ProductLineItem.InventoryID field being a key field and the BQL search defined for this field not returning the InventoryItem selected for the ProductLineItem record you try to delete.

The very first thing the framework does as part of the Delete operation is to invoke FieldUpdating and FieldUpdated handlers for all deleted record key fields. In your case, those handlers fail due to PXSelectorAttribute not able to find the InventoryItem selected for the deleted ProductLineItem record. For more details, see Acumatica API Reference.

The easiest way to resolve this issie is to revise the BQL search on the ProductLineItem.InventoryID field to return both the active items not yet added to the current Product Line and the item selected for the current ProductLineItem record:

Where2<Where<InventoryItem.itemStatus, Equal<InventoryItemStatus.active>,
           And<ProductLineItem.lineID, IsNull>>>,
    Or<InventoryItem.inventoryID, Equal<Current<ProductLineItem.inventoryID>>>>