Solved

How do I update all package lines on the shipment screen?

  • 15 March 2022
  • 6 replies
  • 218 views

Userlevel 5
Badge +1

I have added some code to the SOShipmentEntry to automatically put the unpaid balance into the COD field when adding a new Package if the payment method ID is COD.

Each time a new package is added I need this amount to be split across the total number of packages. Likewise if one is removed it should update all to match.

I have code that will produce a list of the lines and am outputting to the Trace so I can see it’s getting the records correctly.  This is in SOPackageDetailEx_COD_FieldDefaulting:

protected void SOPackageDetailEx_COD_FieldDefaulting(PXCache cache, PXFieldDefaultingEventArgs e, PXFieldDefaulting InvokeBaseHandler)
{
if (InvokeBaseHandler != null)
InvokeBaseHandler(cache, e);
var row = (SOPackageDetailEx)e.Row;
if (row == null) return;

SOShipLine item = Base.Transactions.Select().FirstOrDefault();

// Find how many packages have been added.
// First get all the package records from PackageDetailEx matching this ShipmentNbr

List<SOPackageDetailEx> lines1 = PXSelect<SOPackageDetailEx, Where<SOPackageDetailEx.shipmentNbr, Equal<Required<SOPackageDetailEx.shipmentNbr>>>>.Select(Base, item.ShipmentNbr).FirstTableItems.ToList();

var pkgCount = lines.Count + 1; // because we added a new package
var pkgCOD = unpaidBalance / Convert.ToDecimal(pkgCount);

foreach(SOPackageDetailEx pkgItem in lines)
{
PXTrace.WriteInformation("Package: " + pkgItem.LineNbr + " - " + pkgItem.COD + " - newCOD: " + pkgCOD);
}

e.NewValue = pkgCOD;
}

I’m not sure how to go about updating the previous package lines. I just need to loop through all lines setting the COD field value to pkgCOD and saving it before setting the NewValue.

 

Thanks for any help and sorry if this is totally the wrong way to go about this. I found other code that seemed to do what I wanted and modified it for this purpose.

 

Phil

icon

Best answer by Naveen Boga 15 March 2022, 04:15

View original

6 replies

Userlevel 5
Badge +1

I discovered someone doing a similar thing and modified their code which seems to be working and seems a more correct way to do this:

 

foreach (SOPackageDetailEx package in Base.Packages.Select())
{
Base.Packages.Cache.SetValueExt<SOPackageDetailEx.cOD (package, unpaidBalance / Convert.ToDecimal(Base.Packages.Select().Count+1));
  Base.Packages.Cache.Update(package);
  Base.Actions.PressSave();
}
          
e.NewValue = unpaidBalance / Convert.ToDecimal(Base.Packages.Select().Count+1);

Is there a better way to be doing this?  Also which is the best event handler to update the records when deleting a package. I need to basically do the same thing. I put it in RowUpdated but got an infinite loop of updating and saving.

 

Thanks for any advice,

 

Phil

Userlevel 7
Badge +17

Hi, @ppowell  There are a few inputs from my side. Hope this helps!!

 

From the above code:

  1. You cannot do Cache.Update() in the ROWUpdated event, will lead to an infinite loop, and the instance will be hung.
  2. Base.Actions.press save(); The same way we cannot use the SAVE in the Updated Events.

Inputs:

  1. I’m assuming that this field is for only display purpose, if yes, you can go with the Unbound field.
  2. Write a FieldSelecting event to show the unpaid balance for each package. I have verified the below and it is working great.
  3. Also, attached video recording for your reference.
   protected void SOPackageDetailEx_UsrUnpaidBalByPkg_FieldSelecting(PXCache cache, PXFieldSelectingEventArgs e)
{
SOPackageDetailEx row = (SOPackageDetailEx)e.Row;
if (row != null)
{
decimal? unpaidBal = 150;
foreach (SOPackageDetailEx pkg in Base.Packages.Select())
{
SOPackageDetailExExt pkgLineExt = pkg.GetExtension<SOPackageDetailExExt>();
if (unpaidBal > 0m)
{
Base.Packages.Current = row;
pkgLineExt.UsrUnpaidBalByPkg = unpaidBal / Convert.ToDecimal(Base.Packages.Select().Count);
}
}
Base.Packages.View.RequestRefresh();
}
}

  

Hope this helps!!

Userlevel 5
Badge +1

Thanks Naveen, as always. I think you’re right in that it makes more sense to have it as a calculated unbound field as the issues around updating the other records are too great. I wasn’t able to see the video as I get an error saying the image couldn’t be loaded.

 

Phil

Userlevel 7
Badge +17

Hi, @ppowell  Great 🙂 Thanks for the update.

Sorry, I uploaded a video again for reference.

 

Userlevel 5
Badge +1

Thanks Naveen for the updated video,  I see it works exactly as we want it to. I need to confirm we don’t need to have it on printouts etc but even if someone has to manually type in the value into a field I can have the auto calculated one next to it so they know what to put in which saves time for them to go and find the unpaid balance and manually calculate it.

All the best,

Phil

Userlevel 5
Badge +1

I finally got the go ahead to implement this on our system.  I’m not sure if I’m doing something wrong in how I created the field but I get the following when using the code you provided:

 

\App_RuntimeCode\SOShipmentEntry.cs(67): error CS0246: The type or namespace name 'SOPackageDetailExExt' could not be found (are you missing a using directive or an assembly reference?)

I created the field from within the screens section in Add Data Fields.  Should I have created it in a different way or do I need to add a using directive to the top? I published before adding your code and the field show in the packages tab.

 

Thanks,

 

Phil

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