Slottaje
Slottaje

Reputation: 105

Add Inventory Item lookup to Panel

I've added some custom code to the Item Class screen to create an Inventory Item with the same class. When the user clicks the Create Item button, a panel pops up to enter the Item Name before submitting. I need the field to be a lookup like the original Inventory ID field on the Stock Items screen. I've got the lookup on the panel, but whenever you select an item, it switches back to the very first item in the list.

 public PXFilter<InventoryItem> MyPanel; // in INItemClassMaint extension
 public PXSelect<InventoryItem, Where<InventoryItem.stkItem, Equal<boolTrue>, And<Match<Current<AccessInfo.userName>>>>> Item;

 // on in201000.aspx page

 <px:PXSmartPanel runat="server" ID="CstSmartPanel2" Key="MyPanel" AcceptButtonID="CstButton6" DesignView="Hidden" Caption="Create Item" CaptionVisible="True" LoadOnDemand="True" CreateOnDemand="False">
    <px:PXFormView runat="server" ID="CstFormView3" DataMember="Item" DataSourceID="ds" DefaultControlID="edInventoryCD">
        <Template>
            <px:PXLayoutRule runat="server" ID="CstPXLayoutRule4" StartColumn="True" />
            <px:PXSegmentMask runat="server" ID="CstPXSegmentMask10" DataField="InventoryCD" /></Template></px:PXFormView>
    <px:PXPanel runat="server" ID="CstPanel5" SkinID="Buttons">
        <px:PXButton runat="server" ID="CstButton6" Text="Create" DialogResult="OK">
            <AutoCallBack Command="Save" /></px:PXButton>
        </px:PXPanel></px:PXSmartPanel>

Any ideas on how to correctly do this? Thanks

Upvotes: 1

Views: 398

Answers (1)

RuslanDev
RuslanDev

Reputation: 6778

You were initially on the right path when started with MyPanel data view of the PXFilter type. Very first issue arose with InventoryItem used as main DAC for the MyPanel view:

  1. in the INItemClassMaint BLC there is already a data view with InventoryItem used as main DAC (Items) and by declaring another view with identical main DAC you force both views to share same PXCache instance, which is never suggested unless they are bound to PXForms representing exact same record in UI
  2. data views of the PXFilter type can not be used with DACs which have at least one key field, otherwise the framework invokes Cancel command every time a user changes one of key field values

Below is the sample adding custom dialog on the Item Classes screen to create new Stock Item of the current Item Class:

  • declaration of custom PXSmartPanel in Aspx:

    <px:PXSmartPanel runat="server" ID="CstSmartPanel2" Key="CreateStockItemDialog" Caption="Create Item" AutoRepaint="True"
        AcceptButtonID="CstButton6" CaptionVisible="True" >
        <px:PXFormView runat="server" ID="CstFormView3" DataMember="CreateStockItemDialog" SkinID="Transparent">
            <Template>
                <px:PXLayoutRule runat="server" StartColumn="True" />
                <px:PXSegmentMask runat="server" ID="CstPXSegmentMask10" DataField="InventoryCD" CommitChanges="true" />
            </Template>
        </px:PXFormView>
            <px:PXLayoutRule runat="server" StartRow="True" />
            <px:PXPanel runat="server" ID="CstPanel5" SkinID="Buttons">
                <px:PXButton runat="server" ID="CstButton6" Text="OK" DialogResult="OK" />
        </px:PXPanel>
    </px:PXSmartPanel>
    
  • implementation of the INItemClassMaint BLC extension:

    public class INItemClassMaintExt : PXGraphExtension<INItemClassMaint>
    {
        [Serializable]
        public class CreateStockItemParams : IBqlTable
        {
            #region InventoryCD
            public abstract class inventoryCD : PX.Data.IBqlField
            {
            }
            [PXString]
            [PXUIField(DisplayName = "Inventory ID")]
            public virtual string InventoryCD { get; set; }
            #endregion
        }
    
        public PXFilter<CreateStockItemParams> CreateStockItemDialog;
    
        public PXDBAction<INItemClass> CreateStockItem;
        [PXButton]
        [PXUIField(DisplayName = "Create Stock Item")]
        protected void createStockItem()
        {
            var result = CreateStockItemDialog.AskExt((graph, viewname) =>
            {
                CreateStockItemDialog.Cache.Clear();
            });
            if (result != WebDialogResult.OK) return;
    
            var itemParams = CreateStockItemDialog.Current;
            if (string.IsNullOrEmpty(itemParams.InventoryCD))
            {
                CreateStockItemDialog.Cache.RaiseExceptionHandling<CreateStockItemParams.inventoryCD>(itemParams,
                    itemParams.InventoryCD, new PXSetPropertyException(ErrorMessages.FieldIsEmpty, 
                        PXUIFieldAttribute.GetDisplayName< CreateStockItemParams.inventoryCD>(CreateStockItemDialog.Cache)));
                return;
            }
    
            InventoryItemMaint maint = PXGraph.CreateInstance<InventoryItemMaint>();
            var newItem = new InventoryItem();
            newItem.InventoryCD = itemParams.InventoryCD;
            newItem = maint.Item.Insert(newItem);
            newItem.ItemClassID = Base.itemclass.Current.ItemClassID;
            maint.Item.Update(newItem);
    
            throw new PXRedirectRequiredException(maint, "New Stock Item");
        }
    
        protected void CreateStockItemParams_InventoryCD_FieldSelecting(PXCache sender, PXFieldSelectingEventArgs e)
        {
            e.IsAltered = true;
            object ret = e.ReturnValue;
    
            PXDimensionAttribute restoreCombo = null;
            foreach (PXEventSubscriberAttribute attr in sender.Graph.Caches[typeof(InventoryItem)]
                .GetAttributesReadonly<InventoryItem.inventoryCD>())
            {
                if (attr is PXDimensionAttribute)
                {
                    if (((PXDimensionAttribute)attr).ValidComboRequired)
                    {
                        ((PXDimensionAttribute)attr).ValidComboRequired = false;
                        restoreCombo = (PXDimensionAttribute)attr;
                        break;
                    }
                }
            }
            sender.Graph.Caches[typeof(InventoryItem)].
                RaiseFieldSelecting<InventoryItem.inventoryCD>(null, ref ret, true);
            if (restoreCombo != null)
            {
                restoreCombo.ValidComboRequired = true;
            }
            e.ReturnState = ret;
        }
    
        protected void CreateStockItemParams_InventoryCD_FieldVerifying(PXCache sender, PXFieldVerifyingEventArgs e)
        {
            object val = e.NewValue;
            sender.Graph.Caches[typeof(InventoryItem)].RaiseFieldVerifying<InventoryItem.inventoryCD>(null, ref val);
            var item = (InventoryItem)PXSelect<InventoryItem, Where<InventoryItem.inventoryCD, Equal<Required<InventoryItem.inventoryCD>>>>.SelectWindowed(Base, 0, 1, val);
            if (item != null)
            {
                throw new PXSetPropertyException("Stock Item with Inventory ID {0} already exists.",
                    sender.Graph.Caches[typeof(InventoryItem)].GetValueExt<InventoryItem.inventoryCD>(item));
            }
            e.NewValue = val;
        }
    }
    

Key items to highlight in the INItemClassMaintExt class:

  1. use of custom CreateStockItemParams DAC, which has no key fields defined
  2. INItemClassMaintExt.InventoryCD field handlers for FieldSelecting and FieldVerifying events to replicate behavior (support for multiple segments and segment-level validation) of Inventory ID lookup from the Stock Items screen

Upvotes: 1

Related Questions