Skip to main content

I am attempting to add the SQFTINBOX stock item attribute to the Sales Order Grid.  

 

I have declared a class PXAddAttributeColumns as below: 

  public class PXAddAtttributeColumns : CRAttributesFieldAttribute
{
stringr] _names;
bool _IsForSelector;

public PXAddAtttributeColumns(stringr] names, Type entityType, Type entityIDField, Type classIDField, bool IsForSelector = true)
: base(entityType, entityIDField, classIDField)
{
_names = names;
_IsForSelector = IsForSelector;
}

public override void CacheAttached(PXCache sender)
{
this._IsActive = true;
base.CacheAttached(sender);
}

protected override void AttributeFieldSelecting(PXCache sender, PXFieldSelectingEventArgs e, PXFieldState state, string attributeName, int idx)
{
if (_names.Any(attributeName.Equals))
{
//Out-of-box DisplayName is prefixed with "$Attributes$-" - if you need to take that off.
state.DisplayName = (!String.IsNullOrEmpty(state.DisplayName)) ? (state.DisplayName.Replace("$Attributes$-", "")) : attributeName;
state.Visible = true;
//Requires AutoGenerateColumns="AppendDynamic" for PXGrid Control for dynamic Attribute columns creation
state.Visibility = (_IsForSelector) ? PXUIVisibility.SelectorVisible : PXUIVisibility.Dynamic;
}
base.AttributeFieldSelecting(sender, e, state, attributeName, idx);
}

public override void CommandPreparing(PXCache sender, PXCommandPreparingEventArgs e)
{
base.CommandPreparing(sender, e);

if (e.BqlTable == null && aggregateAttributes && sender.GetItemType().IsDefined(typeof(PXProjectionAttribute), true))
{
e.BqlTable = _BqlTable;
}
}
}

Add Extended SO Line as below:

      public class SOLineExtension : PXCacheExtension<SOLine>
{
public abstract class itemAttributes : IBqlField { }

PXAddAtttributeColumns(new(] {"SQFTINBOX"},
typeof(CSAnswerType.inventoryAnswerType),
typeof(SOLine.inventoryID),
typeof(InventoryItem.itemClassID), false)]
public virtual stringr] ItemAttributes { get; set; }
}

I recieve an error message during validation as shown below: 

Validation started.
Copying the website c:\deployment\sites\#####\Customization\#####\siterootValidation\siterootWebsite
Patching the file c:\deployment\sites\#####\Customization\#####\siterootValidation\siterootWebsite\App_RuntimeCode\PXAddAttributeColumns.cs
Patching the file c:\deployment\sites\#####\Customization\#####\siterootValidation\siterootWebsite\App_RuntimeCode\SOLine.cs
Done
Validating Binary Files
Validating Sql Scripts
Validating the website c:\deployment\sites\#####\Customization\#####\siterootValidation\siterootWebsite
IIS APPPOOL\#####
Building directory '\WebSiteValidationDomain\App_RuntimeCode\'.
\App_RuntimeCode\PXAddAttributeColumns.cs(6): error CS0246: The type or namespace name 'CRAttributesFieldAttribute' could not be found (are you missing a using directive or an assembly reference?)
\App_RuntimeCode\PXAddAttributeColumns.cs(18): error CS0115: 'PXAddAtttributeColumns.CacheAttached(PXCache)': no suitable method found to override
\App_RuntimeCode\PXAddAttributeColumns.cs(24): error CS0115: 'PXAddAtttributeColumns.AttributeFieldSelecting(PXCache, PXFieldSelectingEventArgs, PXFieldState, string, int)': no suitable method found to override
\App_RuntimeCode\PXAddAttributeColumns.cs(37): error CS0115: 'PXAddAtttributeColumns.CommandPreparing(PXCache, PXCommandPreparingEventArgs)': no suitable method found to override
\App_RuntimeCode\SOLine.cs(30): error CS0246: The type or namespace name 'PXAddAtttributeColumnsAttribute' could not be found (are you missing a using directive or an assembly reference?)
\App_RuntimeCode\SOLine.cs(30): error CS0246: The type or namespace name 'PXAddAtttributeColumns' could not be found (are you missing a using directive or an assembly reference?)
\App_RuntimeCode\SOLine.cs(31): error CS0246: The type or namespace name 'CSAnswerType' could not be found (are you missing a using directive or an assembly reference?)
\App_RuntimeCode\PXAddAttributeColumns.cs(6): error CS0246: The type or namespace name 'CRAttributesFieldAttribute' could not be found (are you missing a using directive or an assembly reference?)
Compiler time, in seconds: 3.4108918
Validation failed.

Does anyone know why this might be failing validation or where I am going wrong?  

 

Thank you

 

 

Hi @roberts40  I’m assuming below is your requirement.

In the Stock Items screen, you have an attribute i.e. “SQFTINBOX” and you wanted to populate this attribute field value in SOLine grid, when we add Inventory ID in the Document Details → SOOrder.

 

If yes, below the code for populating the stock item attribute value in SOLine level grid.

 protected virtual void SOLine_InventoryID_FieldUpdated(PXCache sender, PXFieldUpdatedEventArgs e, PXFieldUpdated InvokeBaseHandler)
        {
            InvokeBaseHandler?.Invoke(sender, e);
            SOLine row = (SOLine)e.Row;
            if (row == null) return;
            CSAnswers CSAns = PXSelectJoin<CSAnswers,
                              InnerJoin<InventoryItem, On<InventoryItem.noteID, Equal<CSAnswers.refNoteID>>>,
                              Where<InventoryItem.inventoryID, Equal<Required<InventoryItem.inventoryID>>,
                              And<CSAnswers.attributeID, Equal<Required<CSAnswers.attributeID>>
                              >>>.Select(Base, row.InventoryID, "SQFTINBOX");
            if (CSAns != null)
            {
                SOLineExt rowExt = row.GetExtension<SOLineExt>();
                rowExt.usrCustomerField = CSAns.Value;
            }
        }


@Naveen B Naveen, thank you so much for the response and apologies for my ignorance, I am new to customization projects.  What method would I use to attach this code into a customization project.  

 

Would I 

  1. Add the SO Screen to the customization project, Add a data field, then add this code into the attributes of the data field? Or
  2. Add this into the Code Section of the Acumatica customization project under Graph Extension? 

 


@roberts40  

  • Add a new custom field at Document Details by extending the SOLine DAC
  • Also, Extend the SOOrderEntry graph and add the above code.

Please find the code samples for your reference.

//SOLine Extended DAC

public class SOLineExt : PXCacheExtension<SOLine>
{
#region UsrCustomField

PXDBString(512, IsUnicode = true)]
PXUIField(DisplayName = "Custom Field")]
public virtual string UsrCustomField { get; set; }
public abstract class usrCustomField : BqlString.Field<usrCustomField> { }

#endregion

}





//SOOrderEntry Extended Graph

public class SOOrderEntryExt : PXGraphExtension<SOOrderEntry>
{


protected virtual void SOLine_InventoryID_FieldUpdated(PXCache sender, PXFieldUpdatedEventArgs e, PXFieldUpdated InvokeBaseHandler)
{
InvokeBaseHandler?.Invoke(sender, e);
SOLine row = (SOLine)e.Row;
if (row == null) return;
CSAnswers CSAns = PXSelectJoin<CSAnswers,
InnerJoin<InventoryItem, On<InventoryItem.noteID, Equal<CSAnswers.refNoteID>>>,
Where<InventoryItem.inventoryID, Equal<Required<InventoryItem.inventoryID>>,
And<CSAnswers.attributeID, Equal<Required<CSAnswers.attributeID>>
>>>.Select(Base, row.InventoryID, "SQFTINBOX");
if (CSAns != null)
{
SOLineExt rowExt = row.GetExtension<SOLineExt>();
rowExt.usrCustomerField = CSAns.Value;
}
}
}

 


@Naveen B Thank you I followed your instructions.  I get this error during validation.  

Building directory '\WebSiteValidationDomain\App_RuntimeCode\'.
\App_RuntimeCode\SOLine.cs(33): error CS0246: The type or namespace name 'BqlString' could not be found (are you missing a using directive or an assembly reference?)
\App_RuntimeCode\SOLine.cs(33): error CS0246: The type or namespace name 'BqlString' could not be found (are you missing a using directive or an assembly reference?)

 

Do you know what would be causing this?

 

PS I think I owe you dinner at this point, I really appreciate the help.  


Hi @roberts40  I hope you are seeing the below issue.

 

Please add the “using PX.Data.BQL;” namespace in the SOLine DAC extension shown in the screenshot below and do publish.

 

 


@roberts40  

  • Add a new custom field at Document Details by extending the SOLine DAC
  • Also, Extend the SOOrderEntry graph and add the above code.

Please find the code samples for your reference.

//SOLine Extended DAC

public class SOLineExt : PXCacheExtension<SOLine>
{
#region UsrCustomField

PXDBString(512, IsUnicode = true)]
PXUIField(DisplayName = "Custom Field")]
public virtual string UsrCustomField { get; set; }
public abstract class usrCustomField : BqlString.Field<usrCustomField> { }

#endregion

}





//SOOrderEntry Extended Graph

public class SOOrderEntryExt : PXGraphExtension<SOOrderEntry>
{


protected virtual void SOLine_InventoryID_FieldUpdated(PXCache sender, PXFieldUpdatedEventArgs e, PXFieldUpdated InvokeBaseHandler)
{
InvokeBaseHandler?.Invoke(sender, e);
SOLine row = (SOLine)e.Row;
if (row == null) return;
CSAnswers CSAns = PXSelectJoin<CSAnswers,
InnerJoin<InventoryItem, On<InventoryItem.noteID, Equal<CSAnswers.refNoteID>>>,
Where<InventoryItem.inventoryID, Equal<Required<InventoryItem.inventoryID>>,
And<CSAnswers.attributeID, Equal<Required<CSAnswers.attributeID>>
>>>.Select(Base, row.InventoryID, "SQFTINBOX");
if (CSAns != null)
{
SOLineExt rowExt = row.GetExtension<SOLineExt>();
rowExt.usrCustomerField = CSAns.Value;
}
}
}

 

 

Hi @Naveen B , may I know how would the event be translated if it is in this format since PXSelectJoin returns an error if used with the format below:

protected void _(Events.FieldUpdated<InventoryItem.inventoryID> e)
{

}

On another note, what if I wanted to display multiple attributes for a single inventory ID. Do I have to repeat the code below with different attribute?

CSAnswers CSAns = PXSelectJoin<CSAnswers,
InnerJoin<InventoryItem, On<InventoryItem.noteID, Equal<CSAnswers.refNoteID>>>,
Where<InventoryItem.inventoryID, Equal<Required<InventoryItem.inventoryID>>,
And<CSAnswers.attributeID, Equal<Required<CSAnswers.attributeID>>
>>>.Select(Base, row.InventoryID, "SQFTINBOX");


 


Hi @ericklasimin61  What is the error you are facing with the below code using PXSelectJoin?

I have tried this and I’m NOT seeing any issues. Below is the sample code

 protected void _(Events.FieldUpdated<InventoryItem.inventoryID> e)
{
InventoryItem row = (InventoryItem)e.Row;
if (row != null)
{
CSAnswers CSAns = PXSelectJoin<CSAnswers,
InnerJoin<InventoryItem, On<InventoryItem.noteID, Equal<CSAnswers.refNoteID>>>,
Where<InventoryItem.inventoryID, Equal<Required<InventoryItem.inventoryID>>,
And<CSAnswers.attributeID, Equal<Required<CSAnswers.attributeID>>
>>>.Select(Base, row.InventoryID, "SQFTINBOX");
}
}

You can have a list with the required attributes and loop it with below query, by passing the “Attribute ID” from your list (NO need of repeating the code)

 


Hi @Naveen B , the error is CS0120 as shown below:

 

Thanks for the suggestion on looping it with the query!


Hi @ericklasimin61  Have you written this query in your custom graph or extended graph ?


Hi @Naveen B , you are right, it didn’t return any error. My bad, I was just testing the code out and didn’t notice that I was extending DAC instead of the graph. Thanks for your replies!


Hi Naveen,

I am trying to add a stock item attribute to the SOLine grid per your example and I am receiving the errors listed below.  Any idea what is causing the error?

Thanks in advance for you help.

e2024-07-05 20:32:24.051] \App_RuntimeCode\SOOrderEntry.cs(79): error CS0572: 'usrPerLayer': cannot reference a type through an expression; try 'SOLineExt.usrPerLayer' instead
e2024-07-05 20:32:24.052] \App_RuntimeCode\SOOrderEntry.cs(79): error CS0118: 'SOLineExt.usrPerLayer' is a type but is used like a variable
e2024-07-05 20:32:24.055] \App_RuntimeCode\SOOrderEntry.cs(79): error CS0572: 'usrPerLayer': cannot reference a type through an expression; try 'SOLineExt.usrPerLayer' instead

 

SOOrderEntry graph extension:

namespace PX.Objects.SO
{
public class SOOrderEntryExt : PXGraphExtension<SOOrderEntry>
    {


protected virtual void SOLine_InventoryID_FieldUpdated(PXCache sender, PXFieldUpdatedEventArgs e, PXFieldUpdated InvokeBaseHandler)
        {
            InvokeBaseHandler?.Invoke(sender, e);
            SOLine row = (SOLine)e.Row;
            if (row == null) return;
            CSAnswers CSAns = PXSelectJoin<CSAnswers,
                              InnerJoin<InventoryItem, On<InventoryItem.noteID, Equal<CSAnswers.refNoteID>>>,
                              Where<InventoryItem.inventoryID, Equal<Required<InventoryItem.inventoryID>>,
                              And<CSAnswers.attributeID, Equal<Required<CSAnswers.attributeID>>
                              >>>.Select(Base, row.InventoryID, "PERLAYER");
            if (CSAns != null)
            {
                SOLineExt rowExt = row.GetExtension<SOLineExt>();
                rowExt.usrPerLayer = CSAns.Value;
            }
        }
}

 

SOLine DAC extension:

namespace PX.Objects.SO
{
  public class SOLineExt : PXCacheExtension<PX.Objects.SO.SOLine>
  {
    #region UsrPerLayer
    OPXString]
        public virtual string UsrPerLayer { get; set; }
    public abstract class usrPerLayer: PX.Data.BQL.BqlString.Field<usrPerLayer> { }
    #endregion
  }
}

 


}


 

 

 

 

 

 


Hi Naveen,

Disregard, I was able to resolve the issue.

Best Regards,

Chris


Reply