Solved

Inventory Attributes to the Purchase Order Details Line Items

  • 21 August 2023
  • 15 replies
  • 251 views

Userlevel 1
Badge

Hello Acumatica Community,

i am trying to add the attributes of a stock item to the PO Line in the Details Tab

These Attributes:

For my problem i found this post: 

  • I thought i could transfer that to the PO and add the inventory attributes to the Details Tab.
  • After 2 very long days and suffering i no longer know what to do.
  • I would like you to take a look into the code of my customization.
  • I added a new custom field in POLine which i believe later stores the value of the specific attribute. But i am not sure if i correctly defined which attribute to show.

Here is my Code for the DAC Extension of POLine:

using PX.Common;
using PX.Data.BQL;
using PX.Data.ReferentialIntegrity.Attributes;
using PX.Data;
using PX.Objects.AP;
using PX.Objects.CM.Extensions;
using PX.Objects.Common.Bql;
using PX.Objects.Common.Discount.Attributes;
using PX.Objects.Common.Discount;
using PX.Objects.Common;
using PX.Objects.CR;
using PX.Objects.CS;
using PX.Objects.GL;
using PX.Objects.IN.Matrix.Interfaces;
using PX.Objects.IN;
using PX.Objects.PM;
using PX.Objects.PO;
using PX.Objects.TX;
using PX.Objects;
using System.Collections.Generic;
using System;

namespace PX.Objects.PO
{
public class POLineExt : PXCacheExtension<PX.Objects.PO.POLine>
{
#region UsrAttribute1

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


#endregion
}
}

And here for the Graph Extension POOrderEntry

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using PX.Common;
using PX.Data;
using PX.Objects.GL;
using PX.Objects.CM.Extensions;
using PX.Objects.CS;
using PX.Objects.CR;
using PX.Objects.TX;
using PX.Objects.IN;
using PX.Objects.EP;
using PX.Objects.AP;
using PX.Objects.AR;
using PX.Objects.SO;
using SOOrder = PX.Objects.SO.SOOrder;
using SOLine = PX.Objects.SO.SOLine;
using PX.Data.DependencyInjection;
using PX.Data.ReferentialIntegrity.Attributes;
using PX.LicensePolicy;
using PX.Objects.PM;
using CRLocation = PX.Objects.CR.Standalone.Location;
using PX.Objects.AP.MigrationMode;
using PX.Objects.Common;
using PX.Objects.Common.Discount;
using PX.Data.BQL.Fluent;
using PX.Data.BQL;
using PX.Objects.Common.Bql;
using PX.Objects.Extensions.CostAccrual;
using PX.Objects.DR;
using PX.Data.WorkflowAPI;
using PX.Objects.Extensions;
using PX.Objects.Common.DAC;
using PX.Objects.Common.Scopes;
using PX.Objects.IN.Services;
using PX.Objects.Extensions.MultiCurrency;
using PX.Data.Description;
using PX.Objects;
using PX.Objects.PO;

namespace PX.Objects.PO
{
public class POOrderEntry_Extension : PXGraphExtension<PX.Objects.PO.POOrderEntry>
{
#region Event Handlers
protected virtual void POLine_InventoryID_FieldUpdated(PXCache sender, PXFieldUpdatedEventArgs e, PXFieldUpdated InvokeBaseHandler)
{
InvokeBaseHandler?.Invoke(sender, e);
POLine row = (POLine)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, "MATCHCODE");
if (CSAns != null)
{
POLineExt rowExt = row.GetExtension<POLineExt>();
rowExt.UsrAttribute1 = CSAns.Value;
}
}
}
#endregion
}

Case 1: In POOrderEntry with this:

rowExt.UsrAttribute1 = CSAns.Value;

The compiler shows no error but when i try to open a PO the system gives the error “Invalid column name [POLine].[UsrAttribute1]”

Case 2: In POOrderEntry with this:

rowExt.usrAttribute1 = CSAns.Value;

The following error appears:

\App_RuntimeCode\POOrderEntry.cs(60): error CS0572: 'usrAttribute1': cannot reference a type through an expression; try 'POLineExt.usrAttribute1' instead
\App_RuntimeCode\POOrderEntry.cs(60): error CS0118: 'POLineExt.usrAttribute1' is a type but is used like a variable
\App_RuntimeCode\POOrderEntry.cs(60): error CS0572: 'usrAttribute1': cannot reference a type through an expression; try 'POLineExt.usrAttribute1' instead
 

I would be so grateful for any help! Thanks to anyone who reads this and tries to help me!

icon

Best answer by Zoltan Febert 21 August 2023, 18:08

View original

15 replies

Userlevel 6
Badge +3

Hi @Shurtugal98, your new field is not in the POLine table in the database, you need to add it through the customization editor.

 

Userlevel 7
Badge +5

I think that you’re missing the part of your project that actually adds the UsrAttribute1 to the table. In your customization project, on the left, click Database Scripts.  Then find the Add Customer Column to Table action. Select the POLine table and then add in the properties of your field.

When you publish next, the process will add the column to the database table if it is not already there.

Edit: I took too long to write this. :) zfebert56 has your answer.

Userlevel 1
Badge

@Django @zfebert56 

I have added it the way you mentioned and i now get at least not an error. Thanks so far this has definitely helped! But i am now dealing with the problem that in the POLine it doesnt show the value of the attribute. Do you have any idea what i could be doing wrong besides from that?

Here my POLine:

and here is the stock item attributes on the top:

I looked up the DAC of the CSAnswers and the AttributeID = “GROESSE”
I changed the Attribute to make it more clearly for me which attribute i am trying to get.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using PX.Common;
using PX.Data;
using PX.Objects.GL;
using PX.Objects.CM.Extensions;
using PX.Objects.CS;
using PX.Objects.CR;
using PX.Objects.TX;
using PX.Objects.IN;
using PX.Objects.EP;
using PX.Objects.AP;
using PX.Objects.AR;
using PX.Objects.SO;
using SOOrder = PX.Objects.SO.SOOrder;
using SOLine = PX.Objects.SO.SOLine;
using PX.Data.DependencyInjection;
using PX.Data.ReferentialIntegrity.Attributes;
using PX.LicensePolicy;
using PX.Objects.PM;
using CRLocation = PX.Objects.CR.Standalone.Location;
using PX.Objects.AP.MigrationMode;
using PX.Objects.Common;
using PX.Objects.Common.Discount;
using PX.Data.BQL.Fluent;
using PX.Data.BQL;
using PX.Objects.Common.Bql;
using PX.Objects.Extensions.CostAccrual;
using PX.Objects.DR;
using PX.Data.WorkflowAPI;
using PX.Objects.Extensions;
using PX.Objects.Common.DAC;
using PX.Objects.Common.Scopes;
using PX.Objects.IN.Services;
using PX.Objects.Extensions.MultiCurrency;
using PX.Data.Description;
using PX.Objects;
using PX.Objects.PO;

namespace PX.Objects.PO
{
public class POOrderEntry_Extension : PXGraphExtension<PX.Objects.PO.POOrderEntry>
{
#region Event Handlers
protected virtual void POLine_InventoryID_FieldUpdated(PXCache sender, PXFieldUpdatedEventArgs e, PXFieldUpdated InvokeBaseHandler)
{
InvokeBaseHandler?.Invoke(sender, e);
POLine row = (POLine)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, "GROESSE");
if (CSAns != null)
{
POLineExt rowExt = row.GetExtension<POLineExt>();
rowExt.UsrGroesse = CSAns.Value;
}
}
}
#endregion
}


Thanks for any further help and thank you so much again for helping me!

Userlevel 6
Badge +3

Hi @Shurtugal98,

I tried your code and it does what you need on my instance, when I added a new line to the PO it copied the attribute value. Maybe you don’t find your attribute?

Try to use this in your FieldUpdated event handler:
 

POLineExt rowExt = row.GetExtension<POLineExt>();
if (CSAns != null)
{
rowExt.UsrAttribute1 = CSAns.Value;
}
else
{
rowExt.UsrAttribute1 = "Attribute note found.";
}

 

Userlevel 1
Badge

@zfebert56 Thank you so much! I realized that but i made a mistake. I misclicked when setting up the column. Now i have an conversion error but the i will fix right now. Thanks

Userlevel 1
Badge

@Django @zfebert56 Guys please help me out one last time. I try to save the PO when adding a stock item but i get the error “Conversion failed when converting the nvarchar value 'XL' to data type smallint.” I know that the VSAnswers.Value Field is a nvarchar and my UsrAttribute1 is a string so there should be no problem at all. Why does the PO try to convert it to a smallint and how can i avoid this? So sorry and i really owe you one!

Userlevel 6
Badge +3

@Shurtugal98 Can you confirm that your new field in the database is nvarchar?

Userlevel 1
Badge

@zfebert56 I added it like this: 

I thought this would work because a nvarchar contains string values. 

But in the POLine Data Table ist like this:

 

Userlevel 6
Badge +3

@Shurtugal98 Drop the field from the SQL table and try to republish your customization package.

Userlevel 1
Badge

@zfebert56 Thanks for the reply! I am sorry i dont know exactly what to do. Can you give me an advice?

Userlevel 6
Badge +3

@Shurtugal98 You need to drop the field with SQL Server Management Studio or any other SQL tool, using this command:

ALTER TABLE POLine DROP COLUMN UsrGroesse;

Once it is done, you can publish your package again and it will create UsrGroesse with the correct type.

Userlevel 1
Badge

@zfebert56 Thanks i got it now! Just one last question and i will be thanking you forever. What if i want multiple custom fields to be inserted? How would i have to extend my code? 

Userlevel 6
Badge +3

@Shurtugal98 I am not sure what you need, can you clarify your question?

Userlevel 1
Badge

@zfebert56 I am trying to add another Custom Field where i can store another attribute value. How would i need to extend my code for the POOrderEntry GraphExtension if i need more than 1 Attribute?

Userlevel 6
Badge +3

@Shurtugal98 I would use something like this:

        protected virtual void POLine_InventoryID_FieldUpdated(PXCache sender, PXFieldUpdatedEventArgs e, PXFieldUpdated InvokeBaseHandler)
{
InvokeBaseHandler?.Invoke(sender, e);
var row = (POLine)e.Row;
if (row == null) return;

var rowExt = row.GetExtension<POLineExt>();
rowExt.UsrGroesse = GetAttributeValue(Base, row, "GROESSE");
rowExt.UsrSpieler = GetAttributeValue(Base, row, "SPIELER");
rowExt.UsrStyle = GetAttributeValue(Base, row, "STYLE");
}

protected static string GetAttributeValue(PXGraph graph, POLine row, string AttributeName)
{
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(graph, row.InventoryID, AttributeName);

return CSAns?.Value ?? "Attribute note found.";

}

 

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