0

I'm attempting to insert an INKitRegister item. Here's the code:

KitAssemblyEntry kitGraph = CreateInstance<KitAssemblyEntry>();
INKitRegister kit = new INKitRegister();
kitGraph.Document.Current = kit;
kitGraph.Document.Cache.SetValueExt<INKitRegister.inventoryID>(kit, mixQLine.InventoryID);
// This line is not working 
kitGraph.Document.Cache.SetValueExt<INKitRegister.locationID>(kit, 
scales.LocationID);
kitGraph.Document.Cache.SetValueExt<INKitRegister.uOM>(kit, mixQLine.Uom);
kitGraph.Document.Cache.SetValueExt<INKitRegister.qty>(kit, mixQLine.Qty);
kit = kitGraph.Document.Cache.Update(kit) as INKitRegister;
kitGraph.Actions.PressSave();

If I manually configure the InventoryItem to have a default location assigned, the item inserts properly for all other fields, but if not, it throws this error:

Error: Inserting 'IN Kit Split' record raised at least one error. Please review the errors.

What am I doing wrong?

'The errors':

9/11/2020 2:36:26 PM Error: Error: Inserting 'IN Kit Split' record raised at least one error. Please review the errors. at PX.Data.PXUIFieldAttribute.CommandPreparing(PXCache sender, PXCommandPreparingEventArgs e) at PX.Data.PXCache.OnCommandPreparing(String name, Object row, Object value, PXDBOperation operation, Type table, FieldDescription& description) at PX.Data.PXProjectionAttribute.PersistInserted(PXCache sender, Object row) at PX.Data.PXCache.PersistInserted(Object row, Boolean bypassInterceptor) at PX.Data.PXCache.Persist(PXDBOperation operation) at PX.Data.PXGraph.Persist(Type cacheType, PXDBOperation operation) at PX.Data.PXGraph.Persist() at PX.Data.PXSave.d__2.MoveNext() at PX.Data.PXAction.d__28.MoveNext() at PX.Data.PXAction.d__28.MoveNext() at PX.Web.UI.PXBaseDataSource.tryExecutePendingCommand(String viewName, String[] sortcolumns, Boolean[] descendings, Object[] searches, Object[] parameters, PXFilterRow[] filters, DataSourceSelectArguments arguments, Boolean& closeWindowRequired, Int32& adapterStartRow, Int32& adapterTotalRows) at PX.Web.UI.PXBaseDataSource.ExecuteSelect(String viewName, DataSourceSelectArguments arguments, PXDSSelectArguments pxarguments)

stuartd
  • 70,509
  • 14
  • 132
  • 163
Deetz
  • 329
  • 1
  • 16

2 Answers2

1

The use of SetValueExt looks correct, provided mixQLine and scales are both non-null with the referenced fields also non-null. However, you should simulate the "Insert" button via Document.Insert(kit); to insert your new INKitRegister. Sometimes, you need to fill in a few values on the record (like on Sales Order entering SOType) before you insert, but in most cases I haven't needed to do so. If your record exists, typically you would search for the record via:

Document.Current = Document.Search<keyField>(keyValue);

Use of the Insert method on the view will ensure the record is created with all the proper events firing in the graph. My best guess is that this is the underlying issue, although you may need an interim update on the cache before setting certain fields. (For instance, if the location is tied to the inventoryID, you likely need to update the cache with the inventoryID so that the DAC updates the selector and retrieves locations applicable to the item.)

Untested, but this is how I would do it.

KitAssemblyEntry kitGraph = CreateInstance<KitAssemblyEntry>();

INKitRegister kit = new INKitRegister();
// Sometimes need to set initial values here
kit = kitGraph.Document.Insert(kit);

kitGraph.Document.Cache.SetValueExt<INKitRegister.inventoryID>(kit, mixQLine.InventoryID);

//May need to do an interim update on the cache after setting certain fields
kit = kitGraph.Document.Update(kit);

kitGraph.Document.Cache.SetValueExt<INKitRegister.locationID>(kit, scales.LocationID);
kitGraph.Document.Cache.SetValueExt<INKitRegister.uOM>(kit, mixQLine.Uom);
kitGraph.Document.Cache.SetValueExt<INKitRegister.qty>(kit, mixQLine.Qty);

////////////////////////////////
//Alternate way to to set values
kit.InventoryID = mixQLine.InventoryID;

//May need to do an interim update on the cache after setting certain fields
kit = kitGraph.Document.Update(kit);

kit.LocationID = scales.LocationID;
kit.Qty = mixQLine.Qty;
kit.UOM = mixQLine.Uom;
////////////////////////////////

kit = kitGraph.Document.Update(kit);
kitGraph.Actions.PressSave();
Brian Stevens
  • 1,826
  • 1
  • 7
  • 16
  • Thank you for a detailed explanation. I've not seen the insert (used this way) or search functions used elsewhere, so this will help me beyond this question. I will try these suggestions tomorrow. – Deetz Sep 13 '20 at 22:24
  • 1
    I reformatted the code around Search because I just noticed that it masked the bracket section for keyField as an html tag. Looks ok now. – Brian Stevens Sep 13 '20 at 22:30
  • You have ``kit = kitGraph.Document.Update(kit);`` Is there a reason you're not using the ``Cache`` property? – Deetz Sep 14 '20 at 11:06
  • Is the ``Cache.Update(kit)`` a lower-level function? I did notice I had to cast the result manually from ``Cache.Update``. – Deetz Sep 14 '20 at 11:22
  • Excellent question, and to be honest, I'm not completely sure on the real technical aspect of it. I use View.Update(currentRecordObject) because that is what is in the T220 training course. I look at the view as being interaction with the screen and the cache as access with the data directly. Sometimes, like when you need to just force a value into the DAC, you want to work with the cache layer, but normally you want to work with the presentation layer (view). – Brian Stevens Sep 14 '20 at 11:49
  • Ok, that makes sense. I'm not used to thinking in terms of UI when working in the backend, but it is rather refreshing and makes a lot of sense. The original part of the answer worked exceptionally well. Thank you! – Deetz Sep 14 '20 at 12:00
  • 1
    It is one of the things I like most about customizing Acumatica. I look at it as if I'm automating actual user entry, letting all the normal screen controls (event handlers) do their jobs as if I sat right in front of the screen and entered by hand. When I can't figure out why my code won't work, I repeat the process manually in the screen and look at the results in either a debugging session or directly in the database. Event handlers makes it impossible for me to figure out all the business logic I would have to add into my backend code, but by updating the view, I don't have to! – Brian Stevens Sep 14 '20 at 12:08
0

I have used the below code for one of my projects and it working as expected. This code might be helpful to you.

  KitAssemblyEntry kitGraph = PXGraph.CreateInstance<KitAssemblyEntry>();
                INKitRegister objkitregister = PXCache<INKitRegister>.CreateCopy(kitGraph.Document.Insert(new INKitRegister()));
                objkitregister.InventoryID = kitspecifications.KitInventoryID;
                objkitregister.KitRevisionID = SOKitRevisionID;
                objkitregister.Hold = false;
                objkitregister.Qty = Requiredkitqty;
                objkitregister = kitGraph.Document.Update(objkitregister);                   
                kitGraph.Save.Press();
                if (kitGraph.Actions.Contains("Release"))
                {
                    kitGraph.Actions["Release"].Press();
                }
Naveen B
  • 55
  • 4