Solved

Trouble getting PXSelector to return results in Time Card Entry extenstion


Userlevel 6
Badge +3

My selector returns no data when I try to restrict the results to the WorkgroupID field of the current record. 

If I don’t try to restrict the selector with the current Workgroup value, it returns all records in my custom table, whereas I only want it to return records from the custom table where the WorkgroupID is the same as what was selected on the grid.

These are the UDF’s on the PMTimeActivity table.  They all save to the PMTimeActivity table and function correctly otherwise.

This is the Selector for the UsrProductID field. 

        #region UsrProductID
        [PXDBInt]
        [PXUIField(DisplayName = "Product Code")]
        [PXSelector(typeof(SearchFor<ICSProductCode.productID>.
            Where<ICSProductCode.active.IsEqual<True>.
 And<ICSProductCode.workgroupID.IsEqual<EPTimecardDetail.workgroupID.FromCurrent>>>),
                typeof(ICSProductCode.productCD),
                typeof(ICSProductCode.description),
                SubstituteKey = typeof(ICSProductCode.productCD),
                DescriptionField = typeof(ICSProductCode.description))]
        public int? UsrProductID { get; set; }
        public abstract class usrProductID : PX.Data.BQL.BqlInt.Field<usrProductID> { }
        #endregion

If I remove the  And<ICSProductCode.workgroupID.IsEqual<EPTimecardDetail.workgroupID.FromCurrent»

the selector returns all data from my custom table (which I would expect).

The custom table has a key fleid WorkgroupID.  I only want to return records in the selector where the workgroupID matches the WorkgroupID selected on the current line.

I know that the EPTimecardDetail.workgroupID for the current line has a value of 1.

I know this because in debug, the wgID has a value of one on the rowselected event.

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

            int? wgID = row.WorkgroupID;

        }

I don’t know why my EPTimecardDetail.workgroupID.FromCurrent is not evaluating to only show records from my custom table with WorkgroupID of 1.

I attached the DAC, DAC Extension and Graph Extension if you want to see more details.

Note that if I do not try to restrict the selector to the WorkgroupID of the current record, I can select and save data to the tables.  

This screen is very confusing as the DAC and Graph seem to make references to other classes almost as if they were nested.  

This is the data in my tables so you can see there is a value to join to

 

icon

Best answer by Joe Schmucker 24 January 2023, 00:55

View original

17 replies

Userlevel 7
Badge +5

Hi Joe,

I wonder if you need to do something like this - to add another ‘level’ or editor that will force the selector to refresh based on the grid row that you’re on.

https://stackoverflow.com/questions/49692240/custom-selector-not-refreshing-when-placed-in-grid

Userlevel 6
Badge +3

Hi @ddunn 

Thanks for pointing me there.  In that example, they are just returning a description whereas I am trying to “return” a selector.  However, the AutoRefresh=true was definitely needed here.  I think I recall that issue in a previous job I did.  I was SO EXCITED when I saw that because I thought, THERE IT IS!  :-)

Unfortunately, my Selector still comes up empty.  

For some reason, when the Selector fires, I don’t think it is able to see the current value from the row.  Since the EPTimecardDetail is not really a table, maybe that is why.  I noticed that the EPTimeCardDetail in my selector is not a bright orange.  It is kind of grayed a bit.

I’m wondering if it would be possible to use a FieldUpdated event on the WorkgroupID field to trigger the selector to refresh?  I know how to manually request a refresh on a View, but I don’t know if it is even possible to trigger a refresh on the UsrProductID field.

I’m really at a block here.  I have tried a LOT of different things but I am not able to get this to work.  

Userlevel 5
Badge +1

Hi everybody,

I am not sure in my idea, because selector is very simple for a bug, but maybe try to add In<> command before Where<>, like this:

#region UsrProductID
        [PXDBInt]
        [PXUIField(DisplayName = "Product Code")]
        [PXSelector(typeof(SearchFor<ICSProductCode.productID>.In<SelectFrom<ICSProductCode>.
            Where<ICSProductCode.active.IsEqual<True>.
 And<ICSProductCode.workgroupID.IsEqual<EPTimecardDetail.workgroupID.FromCurrent>>>>),
                typeof(ICSProductCode.productCD),
                typeof(ICSProductCode.description),
                SubstituteKey = typeof(ICSProductCode.productCD),
                DescriptionField = typeof(ICSProductCode.description))]
        public int? UsrProductID { get; set; }
        public abstract class usrProductID : PX.Data.BQL.BqlInt.Field<usrProductID> { }
        #endregion

Userlevel 6
Badge +3

@andriikravetskyi35  I’ll give that a try.  I think the root of the issue is IsEqual<EPTimecardDetail.workgroupID.FromCurrent> doesn’t find the Current of that field.

I think I might be onto a workaround though.  I added a virtual field to my extension dac

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

In the FieldUpdating event for the WorkGroupID field, I set the virtual field to the value on the detail line.

        protected void EPTimecardDetail_WorkGroupID_FieldUpdating(PXCache cache, PXFieldUpdatingEventArgs e)
        {
            EPTimecardDetail row = (EPTimecardDetail)e.Row;
            if (row == null) return;

            PMTimeActivityExt tcd = cache.GetExtension<PMTimeActivityExt>(row);
            if (tcd == null) return;
            tcd.VWorkgroupID = row.WorkgroupID; 
        }
Then, in my selector, I use the virtual field for the current

        [PXSelector(typeof(SearchFor<ICSProductCode.productID>.
            Where<ICSProductCode.active.IsEqual<True>.
            And<ICSProductCode.workgroupID.IsEqual<PMTimeActivityExt.vWorkgroupID.FromCurrent>>>),
                typeof(ICSProductCode.productCD),
                typeof(ICSProductCode.description),
                SubstituteKey = typeof(ICSProductCode.productCD),
                DescriptionField = typeof(ICSProductCode.description))]

Still doesn’t return any data.

Maybe this approach would work or some variant.  

Userlevel 7
Badge +5

Out of curiosity, do you get a different result if you use BQL (vs Fluent). It should be exactly the same but your code should be working.

I think this is what it will look like:

[PXSelector(
typeof(
Search<ICSProductCode.productID,
Where<ICSProductCode.active, IsEqual<True>,
And<ICSProductCode.workgroupID, IsEqual<Current<ICSProductCode.workgroupID)>>>>>),
typeof(ICSProductCode.productCD),
typeof(ICSProductCode.description),
SubstituteKey = typeof(ICSProductCode.productCD),
DescriptionField = typeof(ICSProductCode.description))]

Also, if you run a SQL trace when you open the selector, does it show you the criteria that you’re expecting or is the value for workgroupID null?

Userlevel 6
Badge +3

@ddunn I will try it.  However, for testing, I put a constant of 1 instead of the FromCurrent and it pulls data from my table with a workgroupid of 1.  So, I think the fluent is working.  I’ll give your idea a try though and see if it makes a difference.

I dont know how to run a SQL Trace, but I will figure that out too.

Userlevel 7
Badge +8

@joe21 Can you confirm your grid SyncPosition=True? If not the platform won’t recognize the current row properly.

Userlevel 6
Badge +3

@aaghaei  SyncPosition is set to true

Userlevel 7
Badge +8

What about wgID commitchange? Is it True too?

Userlevel 6
Badge +3

@ddunn  I tried your code  No difference.  I also modified your code to use the EPTimecardDetail.workgroupID that didn’t work either. 

Userlevel 6
Badge +3

The Workgroup field on the grid (native field) is set to commitchange.  I thought that was the solution about 8 hours ago.  :-)  Got really excited when I tried that change.  I thought that was IT!  

Userlevel 7
Badge +8

For testing, can you change the DisplayMode of the workgroupID to Value if it is not to see how it works?

Userlevel 7
Badge +5

And it might be a good time to use the Apply Updates screen’s Restart Application button - sometimes when I’m working away on something for a long time it’s a good item to restart the system to clear out any cached elements.

Userlevel 6
Badge +3

Maybe this will help you guys help me.

I created a virtual field in my DAC extension and put a Default of 2 in it

        #region VWorkgroupID
        [PXInt]
        [PXDefault(2)]
        public int? VWorkgroupID { get; set; }
        public abstract class vWorkgroupID : PX.Data.BQL.BqlInt.Field<vWorkgroupID> { }
        #endregion

It pulls the data from my table where workgroupid = 2.

So, the Selector itself is firing and it is pulling the 2 from the virtual field.

I am trying to see if there is a way I can set that virtual field to the value of the WorkgroupID from the current record.  In the grid, the workgroup field is in the EPTimeCardDetail class.

I tried to update the virtual field in the extension in the FieldUpdating event.

        protected void EPTimecardDetail_WorkGroupID_FieldUpdating(PXCache cache, PXFieldUpdatingEventArgs e)
        {
            EPTimecardDetail row = (EPTimecardDetail)e.Row;
            if (row == null) return;

            PMTimeActivityExt tcd = cache.GetExtension<PMTimeActivityExt>(row);
            if (tcd == null) return;
            tcd.VWorkgroupID = row.WorkgroupID;
            cache.Update(tcd);
        }
Either this code is not really updating the field value, or the sequence of events is not correct and the selector gets fired before I do this update.

If I could find a place to update my virtual field before the selector fires, I think that would do the trick.

 

Userlevel 6
Badge +3

Update.  I added the virtual field to the screen.  When I update the workgroup on the row, the ID value stored in the virtual field is showing correctly in the grid.  But only after I select the workgroup twice.

Is there a way to force the selector field to refresh manually?  When I do a lookup on the product code field, it is still using the Default(2) value.  At least the Selector is returning something, it is just using the default value of the virtual field instead of the value of the virtual field being set in the event handler.

I recycled the application pool for the web site, but that did not correct anything.

After recycling, I noticed that when I updated the workgroup the first time, the virtual field was set to zero.  If I update the field again, it shows the value correctly.  So, I think this virtual field this is not going to work the way I am using it.  You can see the zero in the field after I selected the ICS Workgroup 1.

 

 

Userlevel 6
Badge +3

Thanks guys for your time and efforts.  I’m going to submit a Support request.  If I get it working, I’ll post back here with the resolution.

Userlevel 6
Badge +3

I found a way.  I’m sure it isn’t the best way, but it works.

I created a dummy DAC to store the current workgroupID value on the detail line.

I created a PXFilter that uses the field in the dummy DAC.

In the RowSelected event, I store the current value of the workgroupID from the detail line in the Filter.  Then, in my Selector, I use the current from the Filter.

I know I’m not supposed to do updates to caches in the rowselected event, but we are only working with timecards.  I don’t think it will crash the server.

Here’s the code to get this to work:

Dummy DAC

    [PXCacheName("TempWorkGroupID")]
    //[PXPrimaryGraph(typeof(TimeCardMaintkeep))]
    public class TempWorkGroupID : IBqlTable
    {
        #region WorkgroupID
        [PXInt]
        [PXUIField(DisplayName = "Workgroup ID")]
        public int? WorkgroupID { get; set; }
        public abstract class workgroupID : PX.Data.BQL.BqlInt.Field<workgroupID> { }
        #endregion
    }
 

The selector is now:

        #region UsrProductID
        [PXDBInt]
        [PXUIField(DisplayName = "Product Code")]
        [PXSelector(typeof(SearchFor<ICSProductCode.productID>.
            Where<ICSProductCode.active.IsEqual<True>.
            And<ICSProductCode.workgroupID.IsEqual<TempWorkGroupID.workgroupID.FromCurrent>>>),
                typeof(ICSProductCode.productCD),
                typeof(ICSProductCode.description),
                SubstituteKey = typeof(ICSProductCode.productCD),
                DescriptionField = typeof(ICSProductCode.description))]
        public int? UsrProductID { get; set; }
        public abstract class usrProductID : PX.Data.BQL.BqlInt.Field<usrProductID> { }
        #endregion
 

The Filter is declared as 

        public PXFilter<TempWorkGroupID> TempWorkGroupID;
 

Last but not least, the rowselected handler

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

            PMTimeActivityExt tcd = e.Cache.GetExtension<PMTimeActivityExt>(row);

            if (tcd == null) return;
            TempWorkGroupID tw = new TempWorkGroupID();
            TempWorkGroupID.Current = tw;
            tw.WorkgroupID = row.WorkgroupID;
            TempWorkGroupID.UpdateCurrent();
        }

Not pretty, but it works.

 

Reply


About Acumatica ERP system
Acumatica Cloud ERP provides the best business management solution for transforming your company to thrive in the new digital economy. Built on a future-proof platform with open architecture for rapid integrations, scalability, and ease of use, Acumatica delivers unparalleled value to small and midmarket organizations. Connected Business. Delivered.
© 2008 — 2024  Acumatica, Inc. All rights reserved