Simple Field Changes Using The Workflow Engine

Recently, an ISV product I was working on required the External Ref Nbr. Field to be enabled at all times regardless of the document status. I wanted to share with you a few walls that I bounced off of so perhaps you dont have to.

Firstly, make a graph extension for the sales order screen, and override the configure method. Here is the code snippet the configure method. the fs.AddField<>()

        public override void Configure(PXScreenConfiguration configuration)
        {
            var context = configuration.GetScreenConfigurationContext<SOOrderEntry, SOOrder>();
            context.UpdateScreenConfigurationFor(
                c => c.WithFlows(flowContainer =>
                {
                    flowContainer
                        .Update(SOBehavior.SO, df => df
                            .WithFlowStates(fls =>
                            {
                                fls.Update<SOOrderStatus.completed>(flsc => flsc
                                    .WithFieldStates(fs => fs.AddField<SOOrder.customerRefNbr>()));
                                fls.Update<SOOrderStatus.shipping>(flsc => flsc
                                    .WithFieldStates(fs => fs.AddField<SOOrder.customerRefNbr>()));
                            }));
                }));
        }

Now, the traps start. If you have any experience with the workflow engine, you will probably be like “this is very normal and going to be a very short blog post”. But you will find that simply doing this will not enable the field when the document is “Completed” or “Shipping”. Argghhh, what else?

Gotcha #1 – Using a Second Order Graph Extension

Make sure you are using a second order extension, including a workflow extension reference in your extension. Without this, the workflow will configure properly:

    public class IntercoSOOrderExt : PXGraphExtension<WorkflowSO, SOOrderEntry>
    {
        public override void Configure(PXScreenConfiguration configuration)
        {
            var context = configuration.GetScreenConfigurationContext<SOOrderEntry, SOOrder>();
            context.UpdateScreenConfigurationFor(
                c => c.WithFlows(flowContainer =>
                {
                    flowContainer
                        .Update(SOBehavior.SO, df => df
                            .WithFlowStates(fls =>
                            {
                                fls.Update<SOOrderStatus.completed>(flsc => flsc
                                    .WithFieldStates(fs => fs.AddField<SOOrder.customerRefNbr>()));
                                fls.Update<SOOrderStatus.shipping>(flsc => flsc
                                    .WithFieldStates(fs => fs.AddField<SOOrder.customerRefNbr>()));
                            }));
                }));
        }
}

I am referring to specifically the PXGraphExtension<SOOrderEntry_Workflow, SOOrderEntry> call. Usually, graph extensions are simply marked as PXGraphExtension<BaseGraph>, but in the case of changing workflow via code, one must include the Workflow extension as a type parameter as well.

Gotcha #2 – Non Workflow Considerations

After gotcha #1, you probably would have been thinking all is good. However, there are some non workflow considerations. In the base SalesOrderEntry graph, when the order is completed, the caches are actually set “AllowUpdate” = false. So unless you knew to look for this too, then you would have been frustrated by your lack of progress. Override the rowselected event as follows, and additionally perform this. I thought initially that the workflow would handle everything, however more traditional methods of enabling fields sometimes are also required. Screens like the purchase order screen or other more simple screens usually don’t require this.

        public virtual void SOOrder_RowSelected(PXCache cache, PXRowSelectedEventArgs e, PXRowSelected baseN)
        {
            baseN(cache, e);
            SOOrder doc = e.Row as SOOrder;

            if (doc == null)
            {
                return;
            }
            cache.AllowUpdate = true;
            PXUIFieldAttribute.SetEnabled<SOOrder.customerRefNbr>(cache, null, true);
        }

I hope these code snippets help you override the sales order screen. Happy Coding!