Acumatica PXProjection Issues

89 Views Asked by At

The company I work for manufactures doors, vision panels(VPs/windows), and wall and ceiling panels.

I am attempting to make a new tab on the SO form which will be used for doors and eventually make one for VPs and wall and ceiling panels.

To do this I am trying to utilise the PXProjection and just get that to work first and I am not having any luck, my code is below and if anyone has any advice i would greatly appreciate it.

using System;

namespace PXProjectionTest
{
  public partial class DoorTab : SOLineExt
  {
    [PXProjection(typeof(SelectFrom<SOLineExt,
                              InnerJoin<SOLineExt>.
                                        On<SOLineExt.inventoryID.Equal<SOLine.inventoryID>>.
                             **Where<SOLineExt.usrIsDoor, Equal<true>>>))]**
    public class DoorTab : IBqlTable
    {
      
     #region UsrIsDoor
     [PXDBBool(IsKey = true, BqlField = typeof(SOLineExt.usrIsDoor))]
     [PXUIField(DisplayName = "Is a Door?")]
     public virtual bool? UsrIsDoor { get; set; }
     #endregion
    }
  }
}

I get the error CS1031: Type Expected on line 10 which I have put in bold. I have tried without the first public partial class, without the namespace, and without using.System but nothing seems to be working and I am unable to figure out an error with my code based on my very limited knowledge. I will be very grateful of any advice received as my coding knowledge is very limited, all self taught in the last 3 months.

thanks all, Aleks

1

There are 1 best solutions below

1
Brian Stevens On

As Brendan mentioned, you do not use the PXProjection attribute on the definition of a DAC field.

This is an example of a simple PXProjection:

namespace SSCS.IN
{
    [PXProjection(typeof(Select5<INPIHeader,
        InnerJoin<INPIDetail,
            On<INPIDetail.FK.PIHeader>>,
        Where<INPIHeader.status, Equal<INPIHdrStatus.completed>,
            And<INPIDetail.status, Equal<INPIDetStatus.entered>>>,
        Aggregate<GroupBy<INPIHeader.siteID,
            GroupBy<INPIDetail.inventoryID,
            GroupBy<INPIDetail.subItemID,
            GroupBy<INPIDetail.locationID,
            Max<INPIHeader.countDate>>>>>>>))]
    [Serializable]
    [PXHidden]
    public partial class LastPICountDate : PX.Data.IBqlTable
    {
        #region SiteID
        public abstract class siteID : PX.Data.BQL.BqlInt.Field<siteID> { }
        [Site(BqlField = typeof(INPIHeader.siteID))]
        public virtual Int32? SiteID  {get; set; }
        #endregion
        
        #region InventoryID
        public abstract class inventoryID : PX.Data.BQL.BqlInt.Field<inventoryID> { }
        [Inventory(BqlField = typeof(INPIDetail.inventoryID))]
        public virtual Int32? InventoryID {get; set; }
        #endregion
        
        #region SubItemID
        public abstract class subItemID : PX.Data.BQL.BqlInt.Field<subItemID> { }
        [PXDefault(typeof(Search<InventoryItem.defaultSubItemID,
            Where<InventoryItem.inventoryID, Equal<Current<INPIDetail.inventoryID>>,
            And<InventoryItem.defaultSubItemOnEntry, Equal<boolTrue>>>>))]
        [SubItem(typeof(INPIDetail.inventoryID), BqlField = typeof(INPIDetail.subItemID))]
        public virtual Int32? SubItemID  {get; set; }
        #endregion

        #region LocationID
        public abstract class locationID : PX.Data.BQL.BqlInt.Field<locationID> { }
        [Location(typeof(INPIHeader.siteID), Visibility = PXUIVisibility.SelectorVisible, BqlField = typeof(INPIDetail.locationID))]
        public virtual Int32? LocationID {get; set; }
        #endregion

        #region CountDate
        public abstract class lastCountDate : PX.Data.BQL.BqlDateTime.Field<lastCountDate> { }
        [PXDBDate(BqlField = typeof(INPIHeader.countDate))]
        public virtual DateTime? LastCountDate {get; set; }
        #endregion
    }
}

That said, you seem to indicate that you want to add a new tab item into the SOOrderEntry screen (SO301000). If this is the case, you need your door field added into a DAC Extension and then want to create a view in a graph extension for SOOrderEntry and then use that view for your new tab's data source.

The DAC Extension should look something like this:

namespace SSCS.SO
{
    public sealed class SOLineExt : PXCacheExtension<PX.Objects.SO.SOLine>
    {
        public static bool IsActive() =>
            SSCSAccess.FeatureInstalled<SSCSFeaturesSet.main>();
        
        #region UsrIsDoor
        [PXDBBool]
        [PXDefault(false, PersistingCheck = PXPersistingCheck.Nothing)]
        [PXUIField(DisplayName = "Door")]
        public bool? UsrIsDoor { get; set; }
        public abstract class usrIsDoor : PX.Data.BQL.BqlBool.Field<usrIsDoor> { }
        #endregion
    }
}

The Graph Extension should look something like this:

namespace SSCS.SO
{

    public class SOOrderEntry_Extension : PXGraphExtension<PX.Objects.SOOrderEntry>
    {
        public static bool IsActive() =>
            SSCSAccess.FeatureInstalled<SSCSFeaturesSet.main>();
            
        [PXViewName(SSCS.SO.Messages.ViewMyDoorView)]
        public SelectFrom<SOLine>
            .Where<SOLine.orderType.IsEqual<SOOrder.orderType.FromCurrent>
                .And<SOLine.orderNbr.IsEqual<SOOrder.orderNbr.FromCurrent>
                .And<SOLineExt.isDoor.IsEqual<True>>>>
            .View.ReadOnly Doors;
            
    }
}

You then would set the Datamember on the new tab's grid control to Doors to pull fields from that view.

From here, rinse and repeat for the VP's tab.

If all you want to do is identify which lines of the SO are doors or VP's, then you could just add the fields to the DAC extensions and set accordingly and then display on the main tab using the Transactions view already. This would be simpler and cleaner for the end user unless you specifically need custom views.

Taking this one step further, it would seem to me that these would be stock items which are identified as doors or VP's. As such, it would make even more sense to just capture this on the Inventory Item. (We use the Item Class field,but you could make boolean checkboxes if you prefer.) This would negate the need to mark it on every SO Line if it is based on the stock item directly.