Skip to main content
Solved

Using the Persist method on POLine

  • 22 July 2024
  • 3 replies
  • 32 views

 Hello, 

I can update an inventory item with the code below. I’m not suggesting it’s the best way but it works, the description is updated and saved to the database.

public SelectFrom<InventoryItem>.View InventoryItemView;

public PXAction<InventoryItem> UpdateItem;
public virtual IEnumerable updateItem(PXAdapter adapter)
{
List<InventoryItem> l = InventoryItemView.Select().RowCast<InventoryItem>().ToList<InventoryItem>();
InventoryItemView.Current = l.First();

InventoryItemView.Current.Descr = String.Concat(InventoryItemView.Current.Descr, "X");
InventoryItemView.UpdateCurrent();
InventoryItemView.Cache.Persist(PXDBOperation.Update);

return adapter.Get();
}

Using the same method I can update a sales order line.

public SelectFrom<SOLine>.View SOLineUpdateView;

public PXAction<InventoryItem> UpdateSOLine;
public virtual IEnumerable updateSOLine(PXAdapter adapter)
{
List<SOLine> l = SOLineUpdateView.Select().RowCast<SOLine>().ToList<SOLine>();
SOLineUpdateView.Current = l.First();

SOLineUpdateView.Current.TranDesc = String.Concat(SOLineUpdateView.Current.TranDesc, "X");
SOLineUpdateView.UpdateCurrent();
SOLineUpdateView.Cache.Persist(PXDBOperation.Update);
return adapter.Get();
}

I’ve used similar code to update records for SOOrder, POOrder and ItemClass too, and they all update without any issue.
BUT, if I use the same method on purchase order lines I get an error. Here is the code.

public SelectFrom<POLine>.View POLineUpdateView;

public PXAction<InventoryItem> UpdatePOLine;
nPXButton]
oPXUIField(DisplayName = "Update POLine")]
public virtual IEnumerable updatePOLine(PXAdapter adapter)
{
List<POLine> l = POLineUpdateView.Select().RowCast<POLine>().ToList<POLine>();
POLineUpdateView.Current = l.First();

POLineUpdateView.Current.TranDesc = String.Concat(POLineUpdateView.Current.TranDesc, "X");
POLineUpdateView.UpdateCurrent();
POLineUpdateView.Cache.Persist(PXDBOperation.Update);

return adapter.Get();
}

The error says: Error: 'OrderDate' cannot be empty.

 

I can see that OrderDate has a value before the Persist method is called, but is null afterwards. I cannot understand why this is happening. I’ve checked the POLine DAC but cannot see how updating a record would affect the OrderDate field. 

Can anyone explain this?

3 replies

Userlevel 4
Badge +1

Hello @stephenward03 

Looks like the issue is due to this attribute on OrderDate in POLine

[PXDBDefault(typeof(POOrder.orderDate))]

When the POLine persists, this attribute will attempt to set the order date from the parent POOrder of the line from the order that is set as current in cache. Because you’re on the stock/non-stock items screen, and there’s no view defined to select for POOrders, there won’t be any in cache and so that value for the OrderDate will be null.

 

Since there are also a couple of other POLine fields that rely on defaulting from the parent POOrder, this can be best fixed by adding the following line to set the parent POOrder to current in cache before persisting.

 

Base.Caches[typeof(POOrder)].Current = POLine.FK.Order.FindParent(Base, POLineUpdateView.Current);

 

Userlevel 4
Badge +1

Thanks @NicholasBova52,

I can understand why PXDBDefault would perform its work when a record is inserted into the cache but I didn’t expect it to fire when a record is updated. ‘Default’ suggests that it would only fire when an initial value is required.

But I’ve added the line of code you suggested and it’s working. 

Thank you

Userlevel 4
Badge +1

An important thing to remember here is that there exist two different attributes for setting a default value on a field; PXDBDefault, used by this OrderDate field, and PXDefault.

 

The regular PXDefault attribute works how you described. It will only set a value to the field on insert of the data record to the cache (or when the user explicitly calls SetDefaultExt on the cache for the specified data record), and not on a simple update of the record or other persist operation to the database. PXDBDefault, however, is designed to keep values sync’d between records in a Master-Detail relationship. Generally this is for foreign keys of the detail to the master record, but in this case, OrderDate is not a key field of POLine and simply a field that is designed to be kept in sync with the OrderDate field on the parent POOrder. Because the order date of the order can change independently of the POLines, and it’s possible for the POLines to be inserted into the cache before the values of the dependent fields on the POOrder are generated, PXDBDefault is designed to update the value of the attached field on each persist.

 

Here’s a good article on the help site about this attribute’s use in Master-Detail relationships: Acumatica

Reply