uBAQ to update UD field on approved POs

I am trying to create an updateable dashboard from a uBAQ to update a UD field on existing POs. I have not gotten to the dashboard part yet because I am getting stuck on the uBAQ. We are a SaaS public cloud client so we are on the latest release.

I have been reading a lot of posts from @danbedwards like:

But I keep getting an error on my uBAQ when I click the update button that seems like it is an order of operations issue (PO is not approved and cannot be flagged as Ready to Print):
image
I used the same order on the Set Field Widgets as documented in the linked posts and then I changed the order too, still with no success. I looked at a trace of manually unapproving (the exact PO I am trying to change on the uBAQ - so I have permissions to change this PO) and reapproving and so I adjusted the widget order to the order shown in the trace (I am not very good a reading traces):
image
But it still gives me the same error (PO is not approved and cannot be flagged as Ready to Print). I even bypassed the Set Field widget to make Ready to Print TRUE and I still get this error. The links to other threads were for 10.2.400 but we are on K2021.2.7. Can anyone point me in the right direct as to why I am getting this error?

Is the PO Approved? :man_shrugging:

This PO starts approved, but the method directive on the uBAQ is supposed to unapprove it, change it, and reapprove it.


The first condition statement checks to see if the PO is approved (if not, the base code runs).

I only have 2 updatable fields, approved and my InternalComment_c UD field.
image

I can actually unapprove the PO with this uBAQ, but it will not take the change on my InternalComment field or allow me to reapprove the PO.
image

In the trace, do you see Epicor just setting the Approved Flag to “U” or is it calling a method to unapprove and THAT sets the Status flag to unapproved?

I am not too good at reading the traces, but the Business Object that comes a number of lines before image

image

This trace was run while manually unapproving the PO in Purchase Order Entry module.

I can unapprove the PO with the uBAQ. Then I get list and try to add an InternalComment_c (on the unapproved PO) and now I get this error on the BAQ Analyze tab in Query Execution messages: “The PO has been approved. Changes not allowed.”

Sorry, was in a meeting…

Can you whip up a quick BPM to just Unapprove then check the PO Status in PO Tracker and see what you get.

Mark,
If I can go to Purchase Order Entry and unapprove the PO manually (by unchecking the approved box), how would that be any different than getting a BPM to unapprove the PO? Perhaps I am missing the logic in using a BPM to do this?

Even with a manually unapproved PO, when I try to update the InternalComments_c on the uBAQ, I get the error, “The PO has been approved. Changes not allowed”.
This leads me to believe that the DefaultCode has an issue (because my initial condition checks to see if the PO is approved and if not, it goes to the default code):

// <auto-generated>
// This code was generated by a tool. Any changes made manually will be lost
// the next time this code is regenerated.
// </auto-generated>

using (var updater = this.getDataUpdater("Erp", "PO"))
{
    var resultQuery = queryResultDataset.Results
        .Where(row => !string.IsNullOrEmpty(row.RowMod) && row.RowMod != "P");

    foreach (var ttResult in resultQuery)
    {
        var ds = new Erp.Tablesets.UpdExtPOTableset();

        // Query to object mapping
        {
            var PODetail = new Erp.Tablesets.PODetailRow
            {
                ClassID = ttResult.PODetail_ClassID,
                Company = ttResult.PODetail_Company,
                LineDesc = ttResult.PODetail_LineDesc,
                OpenLine = ttResult.PODetail_OpenLine,
                PartNum = ttResult.PODetail_PartNum,
                POLine = ttResult.PODetail_POLine,
                PONUM = ttResult.PODetail_PONUM,
                UnitCost = ttResult.PODetail_UnitCost,
            };

            PODetail.SetUDField<System.String>("InternalCommentsLine_c", ttResult.PODetail_InternalCommentsLine_c);

            ds.PODetail.Add(PODetail);

            var POHeader = new Erp.Tablesets.POHeaderRow
            {
                ApprovalStatus = ttResult.POHeader_ApprovalStatus,
                Approve = ttResult.POHeader_Approve,
                AutoPrintReady = ttResult.POHeader_AutoPrintReady,
                Company = ttResult.POHeader_Company,
                Confirmed = ttResult.POHeader_Confirmed,
                OpenOrder = ttResult.POHeader_OpenOrder,
                OrderDate = ttResult.POHeader_OrderDate,
                PONum = ttResult.POHeader_PONum,
                PromiseDate = ttResult.POHeader_PromiseDate,
            };

            ds.POHeader.Add(POHeader);

            var PORel = new Erp.Tablesets.PORelRow
            {
                BaseQty = ttResult.PORel_BaseQty,
                Company = ttResult.PORel_Company,
                Plant = ttResult.PORel_Plant,
                POLine = ttResult.PORel_POLine,
                PONum = ttResult.PORel_PONum,
                PORelNum = ttResult.PORel_PORelNum,
            };

            ds.PORel.Add(PORel);
        }

        BOUpdErrorTableset boUpdateErrors = updater.Update(ref ds);
        if (this.BpmDataFormIsPublished()) return;

        ttResult.RowMod = "P";

        // Object to query mapping
        {
            var PODetail = ds.PODetail.FirstOrDefault(
                tableRow => tableRow.Company == ttResult.PODetail_Company
                    && tableRow.POLine == ttResult.PODetail_POLine
                    && tableRow.PONUM == ttResult.PODetail_PONUM);
            if (PODetail == null)
            {
                PODetail = ds.PODetail.LastOrDefault();
            }

            var POHeader = ds.POHeader.FirstOrDefault(
                tableRow => tableRow.Company == ttResult.POHeader_Company
                    && tableRow.PONum == ttResult.POHeader_PONum);
            if (POHeader == null)
            {
                POHeader = ds.POHeader.LastOrDefault();
            }

            var PORel = ds.PORel.FirstOrDefault(
                tableRow => tableRow.Company == ttResult.PORel_Company
                    && tableRow.POLine == ttResult.PORel_POLine
                    && tableRow.PONum == ttResult.PORel_PONum
                    && tableRow.PORelNum == ttResult.PORel_PORelNum);
            if (PORel == null)
            {
                PORel = ds.PORel.LastOrDefault();
            }

            if (PODetail != null)
            {
                ttResult.PODetail_ClassID = PODetail.ClassID;
                ttResult.PODetail_Company = PODetail.Company;
                ttResult.PODetail_InternalCommentsLine_c = PODetail.UDField<System.String>("InternalCommentsLine_c", throwIfNull:false);
                ttResult.PODetail_LineDesc = PODetail.LineDesc;
                ttResult.PODetail_OpenLine = PODetail.OpenLine;
                ttResult.PODetail_PartNum = PODetail.PartNum;
                ttResult.PODetail_POLine = PODetail.POLine;
                ttResult.PODetail_PONUM = PODetail.PONUM;
                ttResult.PODetail_UnitCost = PODetail.UnitCost;
            }

            if (POHeader != null)
            {
                ttResult.POHeader_ApprovalStatus = POHeader.ApprovalStatus;
                ttResult.POHeader_Approve = POHeader.Approve;
                ttResult.POHeader_AutoPrintReady = POHeader.AutoPrintReady;
                ttResult.POHeader_Company = POHeader.Company;
                ttResult.POHeader_Confirmed = POHeader.Confirmed;
                ttResult.POHeader_OpenOrder = POHeader.OpenOrder;
                ttResult.POHeader_OrderDate = POHeader.OrderDate;
                ttResult.POHeader_PONum = POHeader.PONum;
                ttResult.POHeader_PromiseDate = POHeader.PromiseDate;
            }

            if (PORel != null)
            {
                ttResult.PORel_BaseQty = PORel.BaseQty;
                ttResult.PORel_Company = PORel.Company;
                ttResult.PORel_Plant = PORel.Plant;
                ttResult.PORel_POLine = PORel.POLine;
                ttResult.PORel_PONum = PORel.PONum;
                ttResult.PORel_PORelNum = PORel.PORelNum;
            }
        }

        if (boUpdateErrors?.BOUpdError?.Count > 0)
        {
            queryResultDataset.Errors
                .AddRange(
                    boUpdateErrors.BOUpdError
                        .Select(
                            e => new ErrorsUbaqRow
                            {
                                TableName = e.TableName,
                                ErrorRowIdent = ttResult.RowIdent,
                                ErrorText = e.ErrorText,
                                ErrorType = e.ErrorType
                            }));
        }
    }
}

var resultsForDelete = queryResultDataset.Results
    .Where(row => row.RowMod != "P")
    .ToArray();

foreach (var ttResult in resultsForDelete)
{
    queryResultDataset.Results.Remove(ttResult);
}

foreach (var ttResult in queryResultDataset.Results)
{
    ttResult.RowMod = "";
}

So if I make the POHeader Comments field updateable, and in the uBAQ change the Comments and hit update (in the Updatable Query block), I get the following message "Query returned 1 row(s). Updatable query action fulfilled and reported no error.:
image

Then when I go to Get List in the Updatable Query Block:


Then the change in my comment field is GONE. The change I made can be seen in the Analyze list view, but it does not persist when I click Get List.

This is just how I code. I do one thing and make sure it works. If it does, then I move to the next thing. Write the code to unapprove the PO and test the :poop: out of it. When testing, I will log in a second time (even sometime with a different user ID) and check to see that another user sees the PO unapproved and not just me in my development environment.

After following this thread PO Detail Comment Text - Approved PO's - #18 by danbedwards very carefully (and having to recreate the BPM workflow multiple times), I have been able to get my uBAQ to update records (one at a time).

Another issue is on a uBAQ, in Analyze, after you update, you need to Get List to see the actual current status (that tripped me up for a while).

Because I am on Kinetic 2021.2.9, there are no longer tt, so I changed the references to queryResultDataset.Results (wherever the tt references existed).

So I can actually update multiple rows, but I get an error (and then rows do not get re-approved). Text from error:
Business Layer Exception

The table queryResultDataset.Results has more than one record

Exception caught in: Epicor.ServiceModel

Error Detail

Correlation ID: 8630a7dd-f975-4938-bc1a-863012b59bdf
Description: The table queryResultDataset.Results has more than one record
Program: Epicor.Customization.dll
Method: GetSingleRow
Line Number: 73
Column Number: 17
Table: queryResultDataset.Results

Client Stack Trace

at Epicor.ServiceModel.Channels.ImplBase1.ShouldRethrowNonRetryableException(Exception ex, DataSet[] dataSets) at Ice.Proxy.BO.DynamicQueryImpl.Update(DynamicQueryDataSet queryDS, DataSet queryResultDataset) at Ice.Adapters.DynamicQueryAdapter.<>c__DisplayClass37_0.<Update>b__0(DataSet datasetToSend) at Ice.Adapters.DynamicQueryAdapter.ProcessUbaqMethod(String methodName, DataSet updatedDS, Func2 methodExecutor, Boolean refreshQueryResultsDataset)
at Ice.Adapters.DynamicQueryAdapter.Update(DynamicQueryDataSet queryDS, DataSet updatedDS, Boolean refreshQueryResultsDataset)
at Ice.UI.App.BAQDesignerEntry.BAQTransaction.b__374_0(Int32& rowReturned)
at Ice.UI.App.BAQDesignerEntry.Forms.BAQDiagramForm.ShowQueryResults(DataSet dsResults, getQueryResult getResults, ReportAdditionalInfo additionalInfo)
at Ice.UI.App.BAQDesignerEntry.BAQTransaction.CallUpdate()

I was not able to understand how @danbedwards intended how to trigger a refresh after the change is processed. Having the BAQ refresh after the Update is made would be helpful.

So my uBAQ will update multiple dirty rows (even though Supports multiple dirty rows is grey and unchecked), but I get a business logic error: "The table queryResultDataset.Results has more than 1 record.
image

The updates are occuring, but the uBAQ fails to re-approve the POs (for multiple dirty rows only). I made the POHeader_Approve field updatable and I can change the Approve status for a PO one at a time.

Does anyone have any advice on where I should look to fix my issues?