Skip to main content
Answer

PO Screen Customization

  • January 24, 2025
  • 6 replies
  • 137 views

Forum|alt.badge.img+3

Hi Everyone,

I have added a barcode field to the PO screen. The functionality is working fine, but I am facing an issue where, whenever I scan a product for the first time, the OrderQty is automatically set to 2. When I scan the same product again, the OrderQty increases to 3 which is correct .

But i for the first time it should be 1 not 2.

However, for a different product, the OrderQty is correctly set to 1 on the first scan. I have attempted to resolve this issue but have not been successful yet.

Please guide me on how to fix this.

Thanks!

Code:

// Check if a POLine for this InventoryID already exists
            POLine existingLine = Base.Transactions
                .Select()
                .RowCast<POLine>()
                .FirstOrDefault(l => l.InventoryID == item.InventoryID);

            if (existingLine != null)
            {
                PXTrace.WriteInformation($"Existing Line Found: {existingLine.InventoryID}, Current Qty: {existingLine.OrderQty}");

                // If first scan, ensure OrderQty starts at 1
                if (existingLine.OrderQty == null || existingLine.OrderQty == 0)
                {
                    PXTrace.WriteInformation("First Scan Detected, Setting OrderQty to 1");
                    existingLine.OrderQty = 1;
                }
                else
                {
                    PXTrace.WriteInformation("Incrementing Quantity by 1");
                    existingLine.OrderQty += 1;
                }

                Base.Transactions.Update(existingLine);
            }
            else
{
    PXTrace.WriteInformation("No Existing Line Found. Creating New Line.");

   
    POLine newLine = new POLine
    {
        InventoryID = item.InventoryID,
        OrderQty = 1, 
        CuryUnitCost = item.BasePrice
    };

    newLine = Base.Transactions.Insert(newLine);
    Base.Transactions.Cache.SetValue<POLine.orderQty>(newLine, 1); 
}
 

Best answer by tahayabali

Yes this was done long ago and everything is working fine in production

6 replies

DipakNilkanth
Pro III
Forum|alt.badge.img+13

Hi ​@tahayabali,


Try below code snippet.

// Check if a POLine for this InventoryID already exists
POLine existingLine = Base.Transactions
.Select()
.RowCast<POLine>()
.FirstOrDefault(l => l.InventoryID == item.InventoryID);

if (existingLine != null)
{
PXTrace.WriteInformation($"Existing Line Found: {existingLine.InventoryID}, Current Qty: {existingLine.OrderQty}");

// If first scan, ensure OrderQty starts at 1

//removed your code
//if (existingLine.OrderQty == null || existingLine.OrderQty == 0)
//added below line
if (existingLine.OrderQty.GetValueOrDefault() == 0)
{
PXTrace.WriteInformation("First Scan Detected, Setting OrderQty to 1");
existingLine.OrderQty = 1;
}
else
{
PXTrace.WriteInformation("Incrementing Quantity by 1");
existingLine.OrderQty += 1;
}

Base.Transactions.Update(existingLine);
}
else
{
PXTrace.WriteInformation("No Existing Line Found. Creating New Line.");


POLine newLine = new POLine
{
InventoryID = item.InventoryID,
OrderQty = 1,
CuryUnitCost = item.BasePrice
};

newLine = Base.Transactions.Insert(newLine);
Base.Transactions.Cache.SetValue<POLine.orderQty>(newLine, 1);
}

I have modified your if condition, as it might be evaluating null the first time and satisfying the condition twice, resulting in the quantity being set to 2.

Hope, it helps!


Forum|alt.badge.img+3
  • Author
  • Captain I
  • January 25, 2025

@Nilkanth Dipak  Hi, After copy pasting your code when i scan the item no line is updated. I have shared the code file. Please review

 

2nd code:
 

using PX.Data;
using PX.Objects.PO;
using PX.Objects.IN;
using PX.Objects.CS;
using System.Linq;

namespace PX.Objects.PO
{
    /// <summary>
    /// Extends the POOrderEntry graph to handle barcode scanning logic.
    /// </summary>
    public class POOrderEntry_Extension : PXGraphExtension<POOrderEntry>
    {
        #region Event Handlers

        /// <summary>
        /// Triggered when the barcode field is updated on the PO Order.
        /// Looks up the corresponding Inventory Item and adds or increments a POLine.
        /// Does not persist changes automatically.
        /// </summary>
        protected virtual void POOrder_UsrInventoryBarCode_FieldUpdated(
            PXCache cache,
            PXFieldUpdatedEventArgs e,
            PXFieldUpdated BaseMethod)
        {
            // 1. Call the base event handler if it exists
            BaseMethod?.Invoke(cache, e);

            // 2. Get the current POOrder and its extension
            POOrder order = e.Row as POOrder;
            if (order == null) return;

            POOrderExt orderExt = cache.GetExtension<POOrderExt>(order);
            if (string.IsNullOrEmpty(orderExt?.UsrInventoryBarCode))
                return;

            // 3. Lookup the INItemXRef record using the scanned barcode
            INItemXRef xRef = PXSelectJoin<
                INItemXRef,
                InnerJoin<InventoryItem,
                    On<InventoryItem.inventoryID, Equal<INItemXRef.inventoryID>>>,
                Where<INItemXRef.alternateType, Equal<Required<INItemXRef.alternateType>>,
                    And<INItemXRef.alternateID, Equal<Required<INItemXRef.alternateID>>>>>
                .Select(Base, INAlternateType.Barcode, orderExt.UsrInventoryBarCode);

            if (xRef == null)
            {
                // Barcode not recognized
                throw new PXSetPropertyException<POOrderExt.usrInventoryBarCode>(
                    "Barcode not found in the system.");
            }

            // 4. Retrieve the InventoryItem from the cross-reference
            InventoryItem item = PXSelect<
                InventoryItem,
                Where<InventoryItem.inventoryID, Equal<Required<InventoryItem.inventoryID>>>>
                .Select(Base, xRef.InventoryID);

            if (item == null)
            {
                throw new PXSetPropertyException<POOrderExt.usrInventoryBarCode>(
                    "Inventory Item not found.");
            }

            // 5. Check vendor compatibility via POVendorInventory
            POVendorInventory vendorItem = PXSelect<
                POVendorInventory,
                Where<POVendorInventory.inventoryID, Equal<Required<POVendorInventory.inventoryID>>>>
                .Select(Base, item.InventoryID);

            // If the PO doesn't have a VendorID, set it. (Do not persist; just update the UI.)
            if (vendorItem != null)
            {
                if (order.VendorID == null)
                {
                    order.VendorID = vendorItem.VendorID;
                    cache.RaiseFieldUpdated<POOrder.vendorID>(order, order.VendorID);

                    // Update the document so the new Vendor appears in the UI
                    Base.Document.Update(order);
                }
                else if (order.VendorID != vendorItem.VendorID)
                {
                    // We already have a different VendorID set on the PO
                    throw new PXSetPropertyException(
                        "Scanned item belongs to a different vendor.");
                }
            }
            // Optional: If vendorItem is null, decide whether to throw an error
            // or allow the line to be created anyway.

            // 6. Check if a POLine for this InventoryID already exists (accumulate quantity).
            var existingLine = Base.Transactions
                .Select()
                .RowCast<POLine>()    // Convert PXResult<POLine> to POLine
                .FirstOrDefault(l => l.InventoryID == item.InventoryID);

             if (existingLine != null)
            {
                PXTrace.WriteInformation($"Existing Line Found: {existingLine.InventoryID}, Current Qty: {existingLine.OrderQty}");

                // If first scan, ensure OrderQty starts at 1

                 //removed your code
                //if (existingLine.OrderQty == null || existingLine.OrderQty == 0)
               //added below line
          if (existingLine.OrderQty.GetValueOrDefault() == 0)
                {
                    PXTrace.WriteInformation("First Scan Detected, Setting OrderQty to 1");
                    existingLine.OrderQty = 1;
                }
                else
                {
                    PXTrace.WriteInformation("Incrementing Quantity by 1");
                    existingLine.OrderQty += 1;
                }

                Base.Transactions.Update(existingLine);
            }
            else
            {
                // Otherwise, insert a new POLine with a default Qty = 1
                POLine newLine = new POLine
                {
                    InventoryID  = item.InventoryID,
                    OrderQty     = 1,
                    CuryUnitCost = item.BasePrice // or use a custom pricing approach
                };
                Base.Transactions.Insert(newLine);
            }

            // Refresh the transaction lines to show the updated quantity
            Base.Transactions.View.RequestRefresh();

            // 7. Clear the Barcode field after processing (so user can scan another)
            cache.SetValueExt<POOrderExt.usrInventoryBarCode>(order, null);

            // Mark the order as updated, so the user can see changes but not persist them yet
            Base.Document.Update(order);
            cache.IsDirty = true;
        }

        #endregion

        #region Persist Override

        public delegate void PersistDelegate();

        /// <summary>
        /// Overrides the default Persist method.
        /// When the user clicks Save, this method is called.
        /// Automatically releases the PO from Hold before saving if necessary.
        /// </summary>
        [PXOverride]
        public void Persist(PersistDelegate basePersist)
        {
            try
            {
                // If the PO is on Hold, release it from Hold before saving
                POOrder order = Base.Document.Current;
                if (order != null && order.Status == POOrderStatus.Hold)
                {
                    Base.releaseFromHold.Press();
                }

                // Call the standard Persist to actually save the changes
                basePersist();
            }
            catch (PXException ex)
            {
                throw new PXException(ex.Message);
            }
        }

        #endregion
    }
}


DipakNilkanth
Pro III
Forum|alt.badge.img+13

Hi ​@tahayabali, Have you checked the trace? 

If trace didn’t help, try to debug once to check is it satisfying the conditions.


Forum|alt.badge.img+3
  • Author
  • Captain I
  • January 31, 2025

@Nilkanth Dipak hi,

I have checked trace and its saving data two time in if and else both conidtion is getting true., Can we please schedule a call if possible?

 


Chris Hackett
Community Manager
Forum|alt.badge.img
  • Acumatica Community Manager
  • April 25, 2025

Hi ​@tahayabali were you able to find a solution? Thank you!


Forum|alt.badge.img+3
  • Author
  • Captain I
  • Answer
  • April 25, 2025

Yes this was done long ago and everything is working fine in production