Skip to main content
Solved

Showing a custom field in Process Shipments that could come from different DACs


Forum|alt.badge.img+6

I am working on a request to show the Sales Order Number on the Process Shipments screen as a column.

I decided to add some PXDBScalar fields to SOShipment that pulls the last order number from SOOrderShipment.  That business logic works for the client and the field appears on the screen properly.

Process Shipments with custom columns show the last sales order for the given shipment.

When the Action selector is changed to Prepare Drop-Ship Invoice, those columns are blank. That’s because a different select statement is run. The view is called Orders but the data is primarily populated from POReceipt instead of SOShipment.

So I tried adding the same custom PXDBScalar fields to POReceipt. And while I can run a GI against POReceipt to correctly show the custom field values:

The custom fields show up in a GI

 

But the columns on the Process Shipment screen remain blank:

Drop ship receipt records don’t show values in the grid columns

I have SOShipment.UsrLastOrderNbr and POReceipt.UseLastOrderNbr and the column on the screen is looking for a field called UsrLastOrderNbr from the Orders view.

Does it have something to do with the SOInvoiceShipment orders() method?  Or the changing of the captions in SOShipmentFilter_RowSelected?

Best answer by markusray17

    public sealed class SOShipmentExt : PXCacheExtension<SOShipment>
    {
        public static bool IsActive() => true;

        [PXString]
        [PXUIField(DisplayName = "Order Type")]
        public string OrderType { get; set; }
        public abstract class orderType : BqlString.Field<orderType> { }

        [PXString]
        [PXUIField(DisplayName = "Order Nbr")]
        public string OrderNbr { get; set; }
        public abstract class orderNbr : BqlString.Field<orderNbr> { }
    }

Cache Extension with virtual fields

 

 

    public class SOInvoiceShipmentExt : PXGraphExtension<SOInvoiceShipment>
    {
        public static bool IsActive() => true;

        public IEnumerable orders()
        {
            foreach(SOShipment shipment in Base.orders())
            {
                var soShipment = SOOrderShipment.FK.Shipment.SelectChildren(Base, shipment)?.First();

                var shipmentExt = shipment.GetExtension<SOShipmentExt>();

                shipmentExt.OrderType = soShipment?.OrderType;
                shipmentExt.OrderNbr = soShipment?.OrderNbr;

                yield return shipment;

            }
        }
    }

Graph Extension overriding the delegate

 

In mine I grabbed the first record but you could easily change that to Last(using System.Linq) and change the display names. 

View original
Did this topic help you find an answer to your question?

4 replies

Forum|alt.badge.img+5
  • Jr Varsity II
  • 237 replies
  • April 14, 2022

I would just just override the View delegate and populate the virtual field there after calling the base method. Even if it is using  a POReceipt select statement it is still returning SOShipment DAC records and with that data it is easy to pull the SOOrderShipment records.

Trying to use attributes across various DACs is going to get dicey in a situation like this.


Forum|alt.badge.img+5
  • Jr Varsity II
  • 237 replies
  • Answer
  • April 14, 2022
    public sealed class SOShipmentExt : PXCacheExtension<SOShipment>
    {
        public static bool IsActive() => true;

        [PXString]
        [PXUIField(DisplayName = "Order Type")]
        public string OrderType { get; set; }
        public abstract class orderType : BqlString.Field<orderType> { }

        [PXString]
        [PXUIField(DisplayName = "Order Nbr")]
        public string OrderNbr { get; set; }
        public abstract class orderNbr : BqlString.Field<orderNbr> { }
    }

Cache Extension with virtual fields

 

 

    public class SOInvoiceShipmentExt : PXGraphExtension<SOInvoiceShipment>
    {
        public static bool IsActive() => true;

        public IEnumerable orders()
        {
            foreach(SOShipment shipment in Base.orders())
            {
                var soShipment = SOOrderShipment.FK.Shipment.SelectChildren(Base, shipment)?.First();

                var shipmentExt = shipment.GetExtension<SOShipmentExt>();

                shipmentExt.OrderType = soShipment?.OrderType;
                shipmentExt.OrderNbr = soShipment?.OrderNbr;

                yield return shipment;

            }
        }
    }

Graph Extension overriding the delegate

 

In mine I grabbed the first record but you could easily change that to Last(using System.Linq) and change the display names. 


Forum|alt.badge.img+6
  • Author
  • Captain II
  • 562 replies
  • April 14, 2022

Wonderful!  Thank you, @markusray17 - I appreciate the code!  I was working on the override as you suggested but I was making it far more complicated than I needed to.  Cheers!


Forum|alt.badge.img+1
  • Semi-Pro III
  • 77 replies
  • September 27, 2023

I’m trying to do this exact thing with a different custom field.  However, I get “Sequence contains no elements” error on this line:

SOOrderShipment.FK.Shipment.SelectChildren(Base, shipment)?.First();

I also need to do this on the SOShipmentEntry graph and tried this:

public class SOShipmentEntryExt : PXGraphExtension<SOShipmentEntry>
{
    public static bool IsActive() => true;

    protected virtual void _(Events.RowSelected<SOShipment> e)
    {
        SOShipment row = e.Row;

        if (row != null)
        {
            SOOrderShipment.FK.Shipment.SelectChildren(Base, row)?.First();

            var soOrderExt = row.GetExtension<SOOrderExt>();

            var shipmentExt = row.GetExtension<SOShipmentExt>();

            shipmentExt.UsrNeedPurchaseOrder = soOrderExt?.UsrNeedPurchaseOrder;

        }

    }

}

But I get the same error on the SelectChildren line.

I was also originally trying to use PXDBScalar but could not get to work reliably everywhere or would sometimes show true on the wrong SOShipment:

#region UsrNeedPurchaseOrder
[PXDBScalar(typeof(Search2<SOOrderExt.usrNeedPurchaseOrder,
       LeftJoin<SOOrderShipment, On<SOShipment.shipmentNbr, Equal<SOOrderShipment.shipmentNbr>>>,
    Where<SOOrderShipment.shipmentNbr, Equal<Current<SOShipment.shipmentNbr>>>,
       OrderBy<Desc<SOOrderExt.usrNeedPurchaseOrder>>>))]
PXBool]
PXUIField(DisplayName = "Need PO", IsReadOnly = true)]
public virtual bool? UsrNeedPurchaseOrder { get; set; }
public abstract class usrNeedPurchaseOrder : PX.Data.BQL.BqlBool.Field<usrNeedPurchaseOrder> { }
#endregion

So I was really happy when I found this solution, but unfortunately I can’t figure out why it’s not working/crashing either.

UPDATE: changed to use FirstOrDefault() - not crashing now but still not quite right. I’ll keep trying

UPDATE 2: Success!

public class SOInvoiceShipmentExt : PXGraphExtension<SOInvoiceShipment>
{
    public static bool IsActive() => true;

    public IEnumerable orders()
    {
        foreach (SOShipment shipment in Base.orders())
        {
            var soShipment = SOOrderShipment.FK.Shipment.SelectChildren(Base, shipment)?.FirstOrDefault();

            if (soShipment != null)
            {
                SOOrder objOrder = PXSelectJoin<SOOrder, InnerJoin<SOOrderShipment, On<SOOrder.orderType, Equal<SOOrderShipment.orderType>,
                And<SOOrder.orderNbr, Equal<SOOrderShipment.orderNbr>>>>,
                Where<SOOrderShipment.shipmentNbr, Equal<Required<SOOrderShipment.shipmentNbr>>>>.
                Select(Base, soShipment.ShipmentNbr);

                var soOrderExt = objOrder.GetExtension<SOOrderExt>();

                var shipmentExt = shipment.GetExtension<SOShipmentExt>();

                shipmentExt.UsrNeedPurchaseOrder = soOrderExt?.UsrNeedPurchaseOrder;

                yield return shipment;

            }

        }
    }
}

 


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings