Solved

How do I total column of a grid and put the result in the top section on the Kit Specifications screen?

  • 14 December 2022
  • 5 replies
  • 120 views

Userlevel 5
Badge +1

I am using the following code in the Kit Assembly screen which works without errors.  This is based on an answer to a question someone asked that Naveen Boga answered some time ago:

 

try
{
IN.INKitRegisterExt iNKitRegisterExt = PXCache<IN.INKitRegister>.GetExtension<INKitRegisterExt>(row);

decimal? unitCostTotal = Base.Components.Select().FirstTableItems.ToList().Select(x => x.UnitCost).Sum();
int? itemCount = Base.Components.Select().FirstTableItems.ToList().Count;

cache.SetValueExt<INKitRegisterExt.usrAIUnitCostTotal>(row, unitCostTotal);
cache.SetValueExt<INKitRegisterExt.usrAIItemCount>(row, itemCount);

}
catch (Exception error) {
PXTrace.WriteInformation(error);
}

the two custom fields I created are populated correctly.  If I try to apply the same logic to the Kit Specifications screen:

try
{
INKitSpecHdrExt iNKitSpecHdrExt = PXCache<INKitSpecHdr>.GetExtension<INKitSpecHdrExt>(row);

decimal? unitCostTotal = Base.StockDet.Select().FirstTableItems.ToList().Select(x => x.UnitCost).Sum();
int? itemCount = Base.StockDet.Select().FirstTableItems.ToList().Count;

cache.SetValueExt<INKitSpecHdrExt.usrAIUnitCostTotal>(row, unitCostTotal);
cache.SetValueExt<INKitSpecHdrExt.usrAIItemCount>(row, itemCount);

}
catch (Exception error) {
PXTrace.WriteInformation(error);
}

I get the error:

\App_RuntimeCode\INKitSpecMaint.cs(31): error CS1061: 'IEnumerable<INKitSpecStkDet>' does not contain a definition for 'ToList' and no accessible extension method 'ToList' accepting a first argument of type 'IEnumerable<INKitSpecStkDet>' could be found (are you missing a using directive or an assembly reference?)

What is the difference between these two screens? How can I get the total row count and sum of UnitCost on the Kit Specifications screen?

 

Any help would be greatly appreciated,

 

Phil

icon

Best answer by Fernando Amadoz 14 December 2022, 18:58

View original

5 replies

Userlevel 5
Badge +2

@ppowell you seem to be missing the reference to the Linq library.

Add this using clause at the start:

using System.Linq

 

Userlevel 5
Badge +1

@Fernando Amadoz Thanks so much!  I have this working now.  I have another question though.  I have the following now which is giving me the values I need:

protected void INKitSpecHdr_RowSelected(PXCache cache, PXRowSelectedEventArgs e, PXRowSelected InvokeBaseHandler)
{
if(InvokeBaseHandler != null)
InvokeBaseHandler(cache, e);
var row = (INKitSpecHdr)e.Row;

if (row == null) return;

try
{
INKitSpecHdrExt iNKitSpecHdrExt = PXCache<INKitSpecHdr>.GetExtension<INKitSpecHdrExt>(row);

var items = Base.StockDet.Select().FirstTableItems.ToList();

decimal? totalCost = 0;

foreach (var item in items) {

INItemCost inItemCost = PXSelectJoin<
INItemCost,
InnerJoin<InventoryItem,
On<INItemCost.inventoryID, Equal<InventoryItem.inventoryID>,
And<InventoryItem.inventoryID, Equal<Required<InventoryItem.inventoryID>>
>
>
>
>.Select(Base, item.CompInventoryID);

decimal? qty = item.DfltCompQty;
decimal? avgCost = inItemCost.AvgCost;

if (avgCost != null && qty > 0) {
totalCost = totalCost + (avgCost * qty);
}
}

int? itemCount = Base.StockDet.Select().FirstTableItems.ToList().Count;

cache.SetValueExt<INKitSpecHdrExt.usrAIUnitCostTotal>(row, totalCost);
cache.SetValueExt<INKitSpecHdrExt.usrAIItemCount>(row, itemCount);

}
catch (Exception error) {
PXTrace.WriteInformation(error);
}
}

I have read in various places that RowSelected is not supposed to be used for this purpose.  Should I put this in a different event handler and if so, which one?  I want the field to calculate when the screen is opened and also whenever something is added/removed/updated in the Stock Details grid.

Having it in the RowSelected Event does all of this but I think maybe it’s not the ideal place to put it.

 

Thanks for any assistance,

 

 Phil

Userlevel 7
Badge +8

@ppowell

If you look at Acumatica Events Model, the RowSelected event is triggered multiple times before and after events. RowSelected is most suggested for UI controls management otherwise you might experience performance degradations. If you do not need values on the screen to be refreshed instantly, the best place will be the master record RowPersisting. Otherwise, you can write it on the Header RowUpdated. Because of the ConCurrency Control fields on the Header, with every insert, update, or delete, your header record will be anyways updated. 

 

 

Userlevel 5
Badge +1

@aaghaei Thank you for your explanation.

Userlevel 5
Badge +1

For anyone who also has the same question I ended up putting my code in the FieldSelecting Event.  This seems to do what I need and hopefully is a better place than the RowSelected event.  It also means that I don’t need to set the value in the extension as I just set e.ReturnValue to what I need.

If this is wrong please someone let me know.

Example below:

protected void INKitSpecHdr_UsrAIAvgCostTotal_FieldSelecting(PXCache cache, PXFieldSelectingEventArgs e, PXFieldSelecting InvokeBaseHandler)
    {
      if(InvokeBaseHandler != null)
        InvokeBaseHandler(cache, e);
      var row = (INKitSpecHdr)e.Row;
      
      if (row == null) return;

      try
      {
        var items = Base.StockDet.Select().FirstTableItems.ToList();
        
        decimal? totalCost = 0;
        
        foreach (var item in items) {
        
          INItemCost inItemCost = PXSelectJoin<
          INItemCost,
            InnerJoin<InventoryItem,
              On<INItemCost.inventoryID, Equal<InventoryItem.inventoryID>,
                And<InventoryItem.inventoryID, Equal<Required<InventoryItem.inventoryID>>
                >
              >
            >
          >.Select(Base, item.CompInventoryID);
          
          decimal? qty = item.DfltCompQty;
          decimal? avgCost = inItemCost.AvgCost;
          
          if (avgCost != null && qty > 0) {
            totalCost = totalCost + (avgCost * qty);
          }
        }
        e.ReturnValue = totalCost;
      }
      catch (Exception error) {
        PXTrace.WriteInformation(error);
      }
    }

 

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