Skip to main content

I wrote a customization to add a link for any files uploaded to a SO Line item into a Production Order.

It works, but I am breaking all kinds of rules.  I am not supposed to update a cache or do BQL statements in the RowSelected handler.  

The goal is that each time a Production Order is opened on screen AM201500, I do a check against the SO Lines related to the Sales Order for that Production Order and create links to the “Files” on the Production Order.  Each SO Line could have multiple attachments and we want those attachments available on the Production Order.  

Also, there is most likely a better way to accomplish this regardless of which handler I use, but this is the only way I know to do it. 

I would appreciate any inputs/critiques you might have.  

        protected void _(Events.RowSelected<AMProdItem> e)
        {
            var row = (AMProdItem)e.Row;
            if (row.OrdNbr != null)
            {
                using (new PXConnectionScope())
                {
                    //create a generic graph
                    PXGraph genericGraph = new PXGraph();

                    var noteDocCache = genericGraph.Cachestypeof(NoteDoc)];

                    //Get a listing of all SO Line items that have a file attached.
                    //there could be more than one file per line
                    foreach (UploadFile uf in SelectFrom<UploadFile>
                        .InnerJoin<NoteDoc>.On<NoteDoc.fileID.IsEqual<UploadFile.fileID>>
                        .InnerJoin<SOLine>.On<SOLine.noteID.IsEqual<NoteDoc.noteID>>
                        .Where<SOLine.orderNbr.IsEqual<@P.AsString>
                            .And<SOLine.orderType.IsEqual<@P.AsString>>>
                        .View.Select(Base, row.OrdNbr, row.OrdTypeRef))
                    {

                        //see if the uploaded file has already been added to the NoteDoc table for the respective noteID and fileID 
                        NoteDoc searchNoteDoc = SelectFrom<NoteDoc>
                            .Where<NoteDoc.noteID.IsEqual<@P.AsGuid>
                            .And<NoteDoc.fileID.IsEqual<@P.AsGuid>>>
                            .View.Select(Base, row.NoteID, uf.FileID);

                        if (searchNoteDoc == null)
                        {
                            NoteDoc noteDoc = new NoteDoc()
                            {
                                NoteID = row.NoteID,
                                FileID = uf.FileID
                            };
                            noteDocCache.Update(noteDoc);
                            noteDocCache.Persist(PXDBOperation.Insert);
                        }
                    }
                }
            }
        }

Thank you!

Joe Schmucker

Hi @joe21 
How about using graph_Extension Initialize()  method to call your function

public class PXGraph_Extension : PXGraphExtension<PXGraph>

{

public override void Initialize()

{

//--------

}

}
Since your code has a select statement I presume Initialize() could be a better approach than the RowSelected handler


  • KishoK, I’ll give that a try.  thanks for taking the time to give me advice!


Hey @joe21,

Definitely, we should NOT use the BQL’s and Graph Instance creations in the RowSelected event, which will cause performance issues.

Though we can add the BQL’s in Initialize(), this will also cause performance issues in my opinion.

 

As you wanted to run the code block only when only open the Production order, just use a flag and by default, it will be set to false, and once your code executes just mark it as True.

This way you can the code execute the code only once.

 

Hope this helps!!

 


I will put my code block into a separate function and call it from either the RowSelected or Intialize() methods.  I will creat a boolean property “alreadyCalled” to check if the function was already run.  This way as you suggested, it will only run the command once.  However, even if I use a boolean property to ensure it only runs one time, Acumatica is smart enough to know there is a graph.createinstance() in my separate function being called from the handler (doesn’t matter which one I use, it still shows an Acuminator error).  

I think at this point I will take the red squiggles from Acuminator under advisement and simply use my knowledge that my boolean property will flag the calling of the custom function and that I will not be affecting performance of the page.  


Yes, as you are executing your code only once for that record, that will NOT a problem even Acuminator showing the message in RED color. You can have proper comment for the reason you're creating the graph in RowSelected Event, so that when whoever reviewing the code, they can understand the reason for having this code. 


Reply