Skip to main content
Question

Popup Action Button on Receive and Put Away Screen Processes Only Last Selected Location. The previously selected locations are ignored.

  • December 19, 2025
  • 0 replies
  • 8 views

 

I am facing an issue with a customization on the Acumatica 2025 R2 Receive and Put Away screen and would appreciate your guidance.

Issue Description:
I have added a custom Action Button on the Receive and Put Away screen. When the button is clicked, a popup window opens that displays a list of active locations in a grid with selection checkboxes.

The expected behavior is that when I select multiple locations in the popup and confirm the action, all selected locations should be processed and set to inactive.

Actual Behavior:
When more than one location is selected, only the last selected location is being processed and inactivated. The previously selected locations are ignored.

Expected Behavior:
All selected locations in the popup grid should be processed together, and the inactive logic should apply to each selected record.

 

Custom Code Reference

Below is the relevant customization code used for the popup and action button:

using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using PX.Common;
using PX.Data;
using PX.Data.BQL;
using PX.Data.BQL.Fluent;
using PX.BarcodeProcessing;
using PX.Objects.Common;
using PX.Objects.AP;
using PX.Objects.IN;
using PX.Objects.IN.WMS;
using PX.Objects.Extensions;
using PX.Objects.IN.Overrides.INDocumentRelease;
using PX.Objects.PO.Scopes;
using System.Threading;
//using WMSBase = WarehouseManagementSystem<ReceivePutAway, ReceivePutAway.Host>;
using PX.Objects.SO.WMS;
using System.Runtime.Remoting.Messaging;
using AllocateAdjacentLocation;
using PX.Objects.PO;


namespace PX.Objects.PO.WMS
{

    public class ReceivePutAwayExt : ReceivePutAway.ScanExtension
    {
   
    public SelectFrom<AvailableLocationStatus>.View AdjLoc;


    protected virtual IEnumerable adjLoc()
    {
      POReceipt doc = Base.Document.Current;
       string ReceiptNbr = doc?.ReceiptNbr;
       if (ReceiptNbr == null)
        {
              yield break;
        }

        POReceiptSplitToTransferSplitLink  ObjPORecSplit =
            PXSelect<
                POReceiptSplitToTransferSplitLink,
                Where<
                    POReceiptSplitToTransferSplitLink.receiptNbr,
                    Equal<Required<POReceiptSplitToTransferSplitLink.receiptNbr>>>>
            .Select(Base, ReceiptNbr);

      // If location not scanned yet → show all available locations
      if (ObjPORecSplit == null)
      {
          yield break;
      }
   
       INTran  objINTran =
            PXSelect<
                INTran,
                Where<
                    INTran.refNbr,
                    Equal<Required<INTran.refNbr>>>>
            .Select(Base, ObjPORecSplit.TransferRefNbr);
        
    // Get ToLocation LocationCD
    INLocation toLocation = PXSelect<
        INLocation,
        Where<INLocation.locationID,
            Equal<Required<INLocation.locationID>>>>
        .Select(Base,objINTran.ToLocationID);


    if (toLocation == null)
        yield break;

    string toLocCD = toLocation.LocationCD;

  if (string.IsNullOrEmpty(toLocCD))
       yield break;

    // Remove trailing underscores
    string cleanLoc = toLocCD.TrimEnd('_');

    // Split segments
    string[] parts = cleanLoc.Split('-');
    if (parts.Length == 0)
       yield break;

    string lastPart = parts[parts.Length - 1];

    // Read number (ignore leading zeros)
    if (!int.TryParse(lastPart, out int number))
       yield break;

    // Always use 2 digits for next locations
    int digits = 2;   // <<< FIXED HERE — Force 2-digit code

    // Rebuild prefix
    string prefix = cleanLoc.Substring(0, cleanLoc.Length - lastPart.Length);
    int currentNo = int.Parse(lastPart);

  if (string.IsNullOrEmpty(prefix))
       yield break;

    // Query ONLY AvailableLocationStatus

var result =
    SelectFrom<AvailableLocationStatus>
    .Where<AvailableLocationStatus.locationCD.StartsWith<@P.AsString>
          .And<AvailableLocationStatus.siteID.IsEqual<@P.AsInt>>>
    .AggregateTo<
        GroupBy<AvailableLocationStatus.locationID>,
        GroupBy<AvailableLocationStatus.locationCD>>
    .View.Select(Base, prefix,objINTran.SiteID);


    HashSet<int?> seenLocations = new HashSet<int?>();
    foreach (AvailableLocationStatus als in result)
    {
         
  
      // new Way to split Lication

  if (string.IsNullOrEmpty(als.LocationCD))
       yield break;

    // Remove trailing underscores
    string cleanLocs = als.LocationCD.TrimEnd('_');

    // Split segments
    string[] partss = cleanLocs.Split('-');
    if (partss.Length == 0)
        yield break;

    string lastParts = partss[partss.Length - 1];
       int locNo = int.Parse(lastParts);

    // ✅ Include only NEXT adjacent locations
    if (locNo > currentNo)
    {
        yield return als;
    }
    }
}

      
        public PXAction<ScanHeader> AdjLocations;
        [PXButton(CommitChanges = true)]
       // [PXUIField(DisplayName = "Adjacent Locations")]
       [PXUIField(DisplayName = "Adjacent Locations", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select)]
        protected virtual IEnumerable adjLocations(PXAdapter adapter)
        {
        // You can define a constant or a localized string for the message
           const string Caption = "Adjacent Locations";

            // Use the Ask() method with the specific overload that accepts
            // a message/title parameter.
           
         if (AdjLoc.AskExt() == WebDialogResult.OK)
            
            {
            AdjLoc.Cache.IsDirty = false;
                var filter = AdjLoc.Current;
                if (filter == null)
                {
                    return adapter.Get();
                }
      
               POReceipt doc = Base.Document.Current;
              
             if (doc == null)   return adapter.Get();
      
               POReceiptSplitToTransferSplitLink  ObjPORecSplit =
                            PXSelect< POReceiptSplitToTransferSplitLink,
                            Where< POReceiptSplitToTransferSplitLink.receiptNbr, Equal<Required<POReceiptSplitToTransferSplitLink.receiptNbr>>>>
                           .Select(Base, doc.ReceiptNbr);

                // If location not scanned yet → show all available locations
              if (ObjPORecSplit == null)   return adapter.Get();
     
                 INTran  objINTran =
                                  PXSelect<INTran,
                                  Where<INTran.refNbr,Equal<Required<INTran.refNbr>>>>
                                .Select(Base, ObjPORecSplit.TransferRefNbr);
      
               ItemAllocatedLocationsMaint ItemAllocatedLocationsGraph = PXGraph.CreateInstance<ItemAllocatedLocationsMaint>();
              
               INSiteMaint graph = PXGraph.CreateInstance<INSiteMaint>();
           
               // Load warehouse once
               INSite warehouse = PXSelect<INSite,
                                         Where<INSite.siteID, Equal<Required<INSite.siteID>>>>
                                        .Select(graph, objINTran.SiteID);

               graph.site.Current = warehouse;
                 
     
           List<int?> selectedLocationIDs = new List<int?>();  
              // foreach (AvailableLocationStatus obj in AdjLoc.Cache.Cached.Cast<AvailableLocationStatus>())
            //  foreach (AvailableLocationStatus obj in AdjLoc.Cache.Cached.Cast<AvailableLocationStatus>())
     // foreach (AvailableLocationStatus obj in AdjLoc.Cache.Updated)
          foreach (AvailableLocationStatus obj in AdjLoc.Select())
      // foreach (AvailableLocationStatus obj in AdjLoc.Cache.Inserted)
            {
               PXTrace.WriteInformation(
        $"Selected={obj.Selected}"
          );
                PXTrace.WriteInformation(
        $"LocationID={obj.LocationID}, LocationCD={obj.LocationCD}"
          );
               if (obj.Selected == true)
                {    
                  
              selectedLocationIDs.Add(obj.LocationID);
      
      PXTrace.WriteInformation(
        $"ALocationID={obj.LocationID}, ALocationCD={obj.LocationCD}"
          );
  
             
      
              INLocation nextloc = SelectFrom<INLocation>
              .Where<INLocation.locationID.IsEqual<P.AsInt>
              .And<INLocation.siteID.IsEqual<P.AsInt>>>
              .View.Select(Base, obj.LocationID, obj.SiteID)
              .TopFirst;

              if (nextloc == null) return adapter.Get();

              // Set current location in warehouse
              graph.location.Current = nextloc;

              // Deactivate
              nextloc.Active = false;
              graph.location.Update(nextloc);
               }
            }

        if (selectedLocationIDs.Count== 0) return adapter.Get();
        // Save only once
        graph.Actions.PressSave();
      
        int? firstAdjLocationID = null;
        int? secondAdjLocationID = null;
        int? thirdAdjLocationID = null;

        if (selectedLocationIDs.Count >= 1)
            firstAdjLocationID = selectedLocationIDs[0];

        if (selectedLocationIDs.Count >= 2)
            secondAdjLocationID = selectedLocationIDs[1];
      
       if (selectedLocationIDs.Count >= 3)
            thirdAdjLocationID = selectedLocationIDs[2];

        // 4. Insert second split
       ItemAllocatedLocations ObjItemAlloLoc = new ItemAllocatedLocations();
              // ObjItemAlloLoc.TranRefNbr=row.RefNbr;
               ObjItemAlloLoc.InventoryID=objINTran.InventoryID;
               ObjItemAlloLoc.SiteID=objINTran.SiteID;
               ObjItemAlloLoc.ToLocationID=objINTran.ToLocationID;
              
               ObjItemAlloLoc.FirstAdjLocationID = firstAdjLocationID;
               ObjItemAlloLoc.SecondAdjLocationID = secondAdjLocationID;
               ObjItemAlloLoc.ThirdAdjLocationID = thirdAdjLocationID;
               
                ItemAllocatedLocationsGraph.IALView.Insert(ObjItemAlloLoc);

                ItemAllocatedLocationsGraph.Actions.PressSave();
      
     //  AdjLoc.View.RequestRefresh();
     
      
           }
           return adapter.Get();
         
      }
    }

  
}

 

DAC Code 

using System;
using PX.Data;
using PX.Data.BQL;
using PX.Data.BQL.Fluent;

namespace AllocateAdjacentLocation
{
  [Serializable]
  [PXCacheName("AvailableLocationStatus")]
  public class AvailableLocationStatus : PXBqlTable, IBqlTable
  {
     #region Selected
    [PXBool]
   // [PXDefault(false)]    
    [PXUIField(DisplayName="Select")]
    public virtual bool? Selected { get; set; }
    public abstract class selected : PX.Data.BQL.BqlBool.Field<selected> { }
    #endregion
      
    #region RecordID
    [PXDBInt()]
    [PXUIField(DisplayName = "Record ID")]
    public virtual int? RecordID { get; set; }
    public abstract class recordID : PX.Data.BQL.BqlInt.Field<recordID> { }
    #endregion

    #region SiteID
    [PXDBInt()]
    [PXUIField(DisplayName = "Site ID")]
    public virtual int? SiteID { get; set; }
    public abstract class siteID : PX.Data.BQL.BqlInt.Field<siteID> { }
    #endregion


    #region LocationID
    [PXDBInt()]
    [PXUIField(DisplayName = "Location ID")]
    public virtual int? LocationID { get; set; }
    public abstract class locationID : PX.Data.BQL.BqlInt.Field<locationID> { }
    #endregion

    #region LocationCD
    [PXDBString(30, IsUnicode = true, InputMask = "")]
    [PXUIField(DisplayName = "Location CD")]
    public virtual string LocationCD { get; set; }
    public abstract class locationCD : PX.Data.BQL.BqlString.Field<locationCD> { }
    #endregion


    #region Active
    [PXDBBool()]
    [PXUIField(DisplayName = "Active")]
    public virtual bool? Active { get; set; }
    public abstract class active : PX.Data.BQL.BqlBool.Field<active> { }
    #endregion
  }
}

 

Aspx Code Popup code 

 

 <px:PXSmartPanel runat="server" ID="CstSmartPanel1" Height="500px" Width="500px" LoadOnDemand="True" ShowAfterLoad="True" Caption="Adjacent Locations" Key="AdjLoc">
    <px:PXGrid runat="server" ID="CstPXGrid1" Height="300px" Width="100%" DataSourceID="ds" SkinID="Details" AllowFilter="">
      <Levels>
        <px:PXGridLevel DataMember="AdjLoc">
          <Columns>
            <px:PXGridColumn DataField="Selected" Width="60" Type="CheckBox" CommitChanges="True" />
            <px:PXGridColumn DataField="LocationCD" Width="140" />
            <px:PXGridColumn DataField="LocationID" Width="70" /></Columns></px:PXGridLevel></Levels></px:PXGrid>
    <px:PXPanel runat="server" ID="CstPanel2">
      <px:PXButton runat="server" ID="CstButton3" Text="SAVE" DialogResult="OK" />
      <px:PXButton runat="server" ID="CstButton4" Text="CANCEL" DialogResult="Cancel" /></px:PXPanel></px:PXSmartPanel>

 

Thank you for your support.

Best regards,
Purva Deshmukh