Question

Inconsistencies when creating records via graphs

  • 14 February 2024
  • 6 replies
  • 80 views

Userlevel 4
Badge +1

Hi, I’m creating the following records via the appropriate graphs: purchase orders, sales orders, and purchase requisitions. But things are not working as I hoped/expected. I thought the idea of using graphs to create records was that you would benefit from features added to the graph, for example if you select a customer, the graph would automatically set the currency for you. This doesn’t seem to be happening consistently and I’m wondering if I’ve misunderstood something fundamental to Acumatica development. 

My test system has a base currency for GBP 
First, I created a test customer called CUST001 and a test vendor VEND001. These both use USD currency.

Next, I created records in the Acumatica UI. 

For a sales order I enter the customer and press save. The location and currency have been defaulted. The purchase is the same, except I use VEND001.

 

The purchase requisition follows the same idea. I enter the customer as CUST001 and the currency is automatically set to USD.

Finally, I’ve used the code below to create records from code. I believe the code is matching the actions from the UI. I set the customer/vendor, and save the record.

private void CreateTestRecords()
{
//CREATE PURCHASE ORDER
BAccount bAccount1 = Base.Select<BAccount>().FirstOrDefault(x => x.AcctCD == "VEND001");
POOrderEntry pOOrderEntry = PXGraph.CreateInstance<POOrderEntry>();
POOrder pOOrder = (POOrder)pOOrderEntry.Document.Cache.CreateInstance();
pOOrder.VendorID = bAccount1.BAccountID;
pOOrder = pOOrderEntry.Document.Insert(pOOrder);
try
{
pOOrderEntry.Actions.PressSave();
}
catch (Exception ex)
{
string s = ex.Message;
}

//CREATE SALES ORDER
BAccount bAccount2 = Base.Select<BAccount>().FirstOrDefault(x => x.AcctCD == "CUST001");
SOOrderEntry sOOrderEntry = PXGraph.CreateInstance<SOOrderEntry>();
SOOrder sOOrder = (SOOrder)sOOrderEntry.Document.Cache.CreateInstance();
sOOrder.CustomerID = bAccount2.BAccountID;
sOOrder = sOOrderEntry.Document.Insert(sOOrder);
try
{
sOOrderEntry.Actions.PressSave();
}
catch (Exception ex)
{
string s = ex.Message;
}

//CREATE PO REQUISITION
BAccount bAccount3 = Base.Select<BAccount>().FirstOrDefault(x => x.AcctCD == "CUST001");
RQRequisitionEntry rQRequisitionEntry = PXGraph.CreateInstance<RQRequisitionEntry>();
RQRequisition rQRequisition = (RQRequisition)rQRequisitionEntry.Document.Cache.CreateInstance();
rQRequisition.CustomerID = bAccount3.BAccountID;
rQRequisition = rQRequisitionEntry.Document.Insert(rQRequisition);
try
{
rQRequisitionEntry.Actions.PressSave();
}
catch (Exception ex)
{
string s = ex.Message;
}

}

The results from the code don’t match the results from the UI, and I don’t understand why.

On the purchase order the CuryID has been set to GBP (not USD like when using the UI), when Save is pressed an exception is raised saying "The currency 'USD' of the pay-to Supplier 'VEND001' differs from currency 'GBP' of the document."

The sales order is created just the UI version, the currency is set to USD as expected.

The requisition is created but the currency is GBP, not USD. See below.

Can anyone explain why, on the purchase order and the requisition the currency isn’t being set to the customer/vendor currency?
Of course I could update the currency in the code but I thought the reason we create records via graphs was to take advantage of the features and validation built into the graphs. Have I misunderstood something?

Any comments/theories/explanations would be welcome. 


6 replies

Badge +11

Without actually trying your code and then trying it how I would write it, I can’t tell you for sure exactly what may be going wrong, but I would expect you to be able to accomplish what you are trying.

Here’s how I would write the code:

POOrderEntry pOOrderEntry = PXGraph.CreateInstance<POOrderEntry>();
POOrder order = pOOrderEntry.Document.Insert();
pOOrderEntry.Document.SetValueExt<POOrder.vendorID>(order, bAccount1.BAccountID);
pOOrderEntry.Document.Update(order);
try
{
pOOrderEntry.Actions.PressSave();
}
catch (Exception ex)
{
string s = ex.Message;
}

I would suggest trying this. If it works, there are two things that could be affecting it. I would call insert to initialize the POOrder record instead of pOOrderEntry.Document.Cache.CreateInstance(). I would also use pOOrderEntry.Document.SetValueExt and/or pOOrderEntry.Document.Update(order) to make sure the cache is being updated after setting the Vendor. I suspect this may solve it.

Userlevel 4
Badge +1

Thank you for replying @darylbowman
I like the idea of using SetValueExt to ensure the events fire. I’ve adjusted the code to use your suggestions, this is shown below.

BAccount bAccount1 = Base.Select<BAccount>().FirstOrDefault(x => x.AcctCD == "VEND001");
POOrderEntry pOOrderEntry = PXGraph.CreateInstance<POOrderEntry>();
POOrder pOOrder = pOOrderEntry.Document.Insert();
pOOrderEntry.Document.SetValueExt<POOrder.vendorID>(pOOrder, bAccount1.BAccountID);
pOOrderEntry.Document.Update(pOOrder);
try
{
pOOrderEntry.Actions.PressSave();
}
catch (Exception ex)
{
string s = ex.Message;
}

Unfortunately I get the same result. An error saying "The currency 'USD' of the pay-to Supplier 'VEND001' differs from currency 'GBP' of the document."
This is because the pOOrder.CuryID property is set to “GBP”
Using the watch window I can see that:
After the insert line, CuryID defaults to GBP. 
After the SetValueExt line and the Update line, CuryID remains it GBP.

Don’t suppose you have any other ideas?

Badge +11

You could manually call SetDefaultExt<> for that field and see if it fills in correctly. Probably not something you should need to do, but it may work.

If it were me, for curiosity's sake, I would visit the base graph and see where the currency value is actually being set. It should be called in a similar way (SetDefaultExt).

Userlevel 4
Badge +1

I have had a look at the source code for POOrderEntry as you suggested and I may have found something. 

Below is a very cut down version of the source code showing that the FieldUpdated event for VendorID is defined in the main POOrderEntry graph. But the event is overridden by the MultiCurrency class, the currency is set by the overriding class, which then calls the base method.

public class POOrderEntry : PXGraph<POOrderEntry, POOrder>, PXImportAttribute.IPXPrepareItems, IGraphWithInitialization
{
protected virtual void POOrder_VendorID_FieldUpdated(PXCache sender, PXFieldUpdatedEventArgs e)
{
//set a lot of values such as default location and terms etc
}

public class MultiCurrency : MultiCurrencyGraph<POOrderEntry, POOrder>
{
[PXOverride]
public virtual void POOrder_VendorID_FieldUpdated(PXCache sender, PXFieldUpdatedEventArgs e, PXFieldUpdated baseMethod)
{
POOrder pOOrder = (POOrder)e.Row;
if (e.ExternalCall || pOOrder == null || pOOrder.CuryID == null || pOOrder.OverrideCurrency == true)
{
SourceFieldUpdated<POOrder.curyInfoID, POOrder.curyID, POOrder.orderDate>(sender, pOOrder);
}

baseMethod(sender, e);
}
}
}

When I use the following to update the vendor id I think the FieldUpdated event from POOrderEntry is being called and not the overridden FieldUpdated event from the MultiCurrency class. This would explain why location is set but currency is not.

pOOrderEntry.Document.SetValueExt<POOrder.vendorID>(pOOrder, bAccount1.BAccountID);

Problem is, I don’t know how to instantiate POOrderEntry as the MultiCurrency class, or whether I should need to. Does anyone have any suggestions?

Userlevel 7
Badge

Hi @stephenward03 were you able to find a solution? Thank you!

Userlevel 4
Badge +1

Hi @Chris Hackett , I don’t really have a ‘solution’ as such. I was really trying to understand why using a graph in code produces different results to using a graph in the UI. I’m running into this problem quite a lot in different parts of the system but this PO example seems to be a good but simple example, requiring only small code sample. I really expected the graph to populate the vendor’s currency for me in this case. If it doesn’t I would like to understand why and how to make that happen. The alternative is to search for the currency and set it myself, but surely this the correct approach - I thought the idea of using a graph was that we can also use the inbuilt business logic of the graph. Problems like this leave me feeling less confident in developing using Acumatica as it can sometimes feel a bit random. If you had a contact who could explain what is happening that would be much appreciated. 

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