Solved

How to determine all ship lines have been deleted from coding's perspective?

  • 13 January 2021
  • 6 replies
  • 56 views

Userlevel 4
Badge

Hello,

        we have a little customization that to count each ship line’s qty according to the item’s temperature zone(which is also a customization field, but it does not matter here).

        It would be almost perfect, however it is having a little issue.

         If someone clear/delete all ship lines and save, the “totaldryunits” would not be set to 0.

        I read the code lines, it looks like

  foreach (SOShipLine line in Base.Transactions.Select())

      this line would not be triggered, if all ship lines were cleared.

 

        I am not good at coding , can anyone help me how to trigger the total reset?

icon

Best answer by Naveen B 14 January 2021, 11:10

Hi @ray20 ,

We can not include the above logic in the cache attached event, but instead of having this code “RowSelected” it's better to write a code in the RowUpdated event and it is the recommended approach.

I have modified the above code a little bit. Please find the code below and verify.

 

Hope this helps!!

        protected void SOShipment_RowUpdated(PXCache cache, PXRowUpdatedEventArgs e, PXRowUpdated InvokeBaseHandler)
{
InvokeBaseHandler?.Invoke(cache, e);
var row = (SOShipment)e.Row;
if (row == null) return;
decimal totalUnits = 0M;
decimal totalDryUnits = 0M; //to calculate only dry items 20201009
foreach (SOShipLine line in Base.Transactions.Select())
{
InventoryItem item = PXSelect<InventoryItem, Where<InventoryItem.inventoryID, Equal<Required<InventoryItem.inventoryID>>,
And<InventoryItem.stkItem, Equal<boolTrue>>>>.Select(Base, line.InventoryID); //Only stock item count shipped units, non-stock did not count
if (item != null)
{
SOShipLineExt soShipLineExt = line.GetExtension<SOShipLineExt>();
var units = 0M;
if (soShipLineExt.UsrCWT == true) //For CWI, did not use shipped qty as shipped units, using split lines instead
{
units = Convert.ToDecimal(soShipLineExt.UsrTotalWgt);
}
else
{
units = Convert.ToDecimal(line.Qty);
}
totalUnits = totalUnits + Convert.ToDecimal(units);

if (item.GetExtension<InventoryItemExt>().UsrTempZone == 0)
{
totalDryUnits = totalDryUnits + Convert.ToDecimal(units);
}
}
}
cache.SetValueExt<SOShipmentExt.usrTotalUnits>(row, Convert.ToDecimal(totalUnits));
cache.SetValueExt<SOShipmentExt.usrTotalDryUnits>(row, Convert.ToDecimal(totalDryUnits));
}
View original

6 replies

Userlevel 4
Badge +1

Hi @ray20 ,

As  per my knowledge, It is NOT recommended to use select statements in the “RowSelected” event, as this event will fire multiple times on each commit of the row.

The below article can help you get the sum from the grid records and display it in the header section.

https://asiablog.acumatica.com/2019/06/calculating-grid-totals-on-a-form.html

 

Hope this helps!!

Userlevel 4
Badge

@Naveen B 
Thank you . You are right, put codes in RowSelected() event would trigger a lot of times when any field is changing/changed. Yes, I heard that.
However, we are using this method for a long time, and the performance has not been highly effected. Maybe just count 10+ lines every sec is no big issue for current computer.
so I’d like to go with current method just having the issue fixed.

the article you showed is also fantastic, but the writer did not put every detail in it, so it is a little bit beyond my current ability. I am not a coder , I am just a IT admin .

So I will try to learn it in the future, Thank you for sharing.

Userlevel 4
Badge +1

Hi @ray20 

I’m NOT sure whether the above code will work for all the scenarios and it looks like work around approach.

 

 I just worked on it and it is working as expected with all the scenarios. 

Please find the source code below and it is very short and simple :relaxed:

Newly created DAC field

 public class SOShipmentExt : PXCacheExtension<SOShipment>
    {        
        #region TotalShipmentQty
        [PXDBDecimal()]
        [PXUIField(DisplayName = "Total Qty.")]
        public virtual decimal? TotalShipmentQty { get; set; }
        public abstract class totalShipmentQty : BqlDecimal.Field<totalShipmentQty> { }
        #endregion
    }

Calculate sum of ShipLines Qtys

 public class SOShipmentEntryExt : PXGraphExtension<SOShipmentEntry>
    { 
        [PXMergeAttributes(Method = MergeMethod.Append)]
        [PXFormula(null, typeof(SumCalc<SOShipmentAMIExt.totalShipmentQty>))]
        protected void SOShipLine_ShippedQty_CacheAttached(PXCache sender)
        { }
    }

Hope this helps!!

 

 

 

Userlevel 4
Badge +1

Hi @ray20 ,

We can not include the above logic in the cache attached event, but instead of having this code “RowSelected” it's better to write a code in the RowUpdated event and it is the recommended approach.

I have modified the above code a little bit. Please find the code below and verify.

 

Hope this helps!!

        protected void SOShipment_RowUpdated(PXCache cache, PXRowUpdatedEventArgs e, PXRowUpdated InvokeBaseHandler)
{
InvokeBaseHandler?.Invoke(cache, e);
var row = (SOShipment)e.Row;
if (row == null) return;
decimal totalUnits = 0M;
decimal totalDryUnits = 0M; //to calculate only dry items 20201009
foreach (SOShipLine line in Base.Transactions.Select())
{
InventoryItem item = PXSelect<InventoryItem, Where<InventoryItem.inventoryID, Equal<Required<InventoryItem.inventoryID>>,
And<InventoryItem.stkItem, Equal<boolTrue>>>>.Select(Base, line.InventoryID); //Only stock item count shipped units, non-stock did not count
if (item != null)
{
SOShipLineExt soShipLineExt = line.GetExtension<SOShipLineExt>();
var units = 0M;
if (soShipLineExt.UsrCWT == true) //For CWI, did not use shipped qty as shipped units, using split lines instead
{
units = Convert.ToDecimal(soShipLineExt.UsrTotalWgt);
}
else
{
units = Convert.ToDecimal(line.Qty);
}
totalUnits = totalUnits + Convert.ToDecimal(units);

if (item.GetExtension<InventoryItemExt>().UsrTempZone == 0)
{
totalDryUnits = totalDryUnits + Convert.ToDecimal(units);
}
}
}
cache.SetValueExt<SOShipmentExt.usrTotalUnits>(row, Convert.ToDecimal(totalUnits));
cache.SetValueExt<SOShipmentExt.usrTotalDryUnits>(row, Convert.ToDecimal(totalDryUnits));
}
Userlevel 4
Badge

hello,

   I’ve found a way, it is definitely not the best. It is just a merely workable.

I am using the original field’s updated event to change my 2 customized fileds

 

    protected void SOShipment_ShipmentQty_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e)
    {
      
      var row = (SOShipment)e.Row;
if (row != null)
  {
        if (row.ShipmentQty == 0m)
       {            

         cache.SetValue<SOShipmentExt.usrTotalUnits>(row, 0m);
         cache.SetValue<SOShipmentExt.usrTotalDryUnits>(row, 0m);
         } 
   }
      
    }

Userlevel 4
Badge

@Naveen B 
Thanks, Thanks.  That’s very kind of you to go the extra extra miles.

However, the case we met is a little bit complicated. The calculation is a little complex.

Take the “DryUnits” for example.
1, It will only count all “stock” item, which means 
Inventoryitem.Isstock = true

2, it will only count  InventoryItem.UsrTempzone = “Dry”         Items.

 

3, We have some “catch weight” item, which we put lb which is the base uom in the main shipline, and input the box’s qty in shiplinesplit. 
To count into the “Units”, we did not count the lbs, we count the count lines of the splitlines.
We assume that each shiplinesplit stands for 1 box.

please find my poor code here

I don’t know how to convert these poor codes to your method.

    protected void SOShipment_RowSelected(PXCache cache, PXRowSelectedEventArgs e)
{

var row = (SOShipment)e.Row;
decimal totalUnits = 0M;
decimal totalDryUnits = 0M; //to calculate only dry items 20201009
foreach (SOShipLine line in Base.Transactions.Select())
{
if (line != null)
{
InventoryItem item = PXSelect<InventoryItem,
Where<InventoryItem.inventoryID, Equal<Required<InventoryItem.inventoryID>>>>
.Select(Base, line.InventoryID);
if (item != null)
{
InventoryItemExt rowExt = PXCache<InventoryItem>.GetExtension<InventoryItemExt>(item);
if (item.StkItem ==true) //Only stock item count shipped units, non-stock did not count
{
SOShipLineExt soShipLineExt = line.GetExtension<SOShipLineExt>();
var units = 0M;
if (soShipLineExt.UsrCWT == true) //For CWI, did not use shipped qty as shipped units, using split lines instead
{
units =Convert.ToDecimal(soShipLineExt.UsrTotalWgt);
}
else
{
units = Convert.ToDecimal(line.Qty);
}
var temp = Convert.ToDecimal(units);
totalUnits = totalUnits + temp;
if (rowExt.UsrTempZone == 0)
{
totalDryUnits = totalDryUnits + temp;
}
};
}
}

var shippedunits= Convert.ToDecimal(totalUnits);
var shippeddryunits= Convert.ToDecimal(totalDryUnits);
if (totalUnits != null)
{
cache.SetValue<SOShipmentExt.usrTotalUnits>(row, shippedunits);
}
if (totalDryUnits != null)
{
cache.SetValue<SOShipmentExt.usrTotalDryUnits>(row, shippeddryunits);
}
}

 

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 — 2020  Acumatica, Inc. All rights reserved