0
votes

I have a custom graph with multiple grids under different tabs. Each grid has a column for sales order order numbers, which have redirect actions to the SOOrderEntry graph. One of the grids use an action with this code to find and insert the sales order into the redirected graph, and this works fine:

        SOOrderEntry graph = PXGraph.CreateInstance<SOOrderEntry>();
        graph.Document.Current = graph.Document.Search<SOOrder.orderNbr>(row.OrderNbr);

However, using that same code in an action for a different grid does not work. Stepping through the debugger shows that

graph.Document.Search<SOOrder.orderNbr>(row.OrderNbr);

returns an empty result.

Each action has DependOnGrid=true set in the pages data source, each grid has SyncPosition=true. Even when hardcoding a string order number into the search parameter it returns an empty result.

The workaround I've found to work is to use

PXSelect<SOOrder>.Search<SOOrder.orderNbr, SOOrder.orderType>(graph, row.OrderNbr, row.OrderType);

within the actions that aren't working.

Has anyone experienced this or maybe has some insight into what's going on here? It's strange to me that very similar redirect actions within the same graph need different code to work properly.

Edit: adding the view definitions

This is the view that uses the action with Search to find the needed document.

        public PXSelectReadonly2<
        SOOrder, 
        InnerJoin<BAccount, 
            On<SOOrder.customerID, Equal<BAccount.bAccountID>>,
        LeftJoin<STSalesTerritory, 
            On<BAccountExt.usrTerritoryID, Equal<STSalesTerritory.territoryID>>>>,
        Where2<
            Where<SOOrder.orderType, Equal<SOOrderTypeConstants.salesOrder>,
                And<SOOrder.status, NotEqual<SOOrderStatus.completed>,
                And<SOOrder.status, NotEqual<SOOrderStatus.invoiced>,
                And<SOOrder.status, NotEqual<SOOrderStatus.cancelled>>>>>,
            And<
            Where2<
                Where<Current<STSalesTerritoryInqFilter.ownerID>, IsNotNull, 
                    And<Current<STSalesTerritoryInqFilter.territoryID>, IsNull,
                    And<Current<STSalesTerritoryInqFilter.repID>, IsNull,
                    And<BAccountExt.usrTerritoryID, IsNull,
                    And<SOOrder.ownerID, Equal<Current<STSalesTerritoryInqFilter.ownerID>>>>>>>,
                Or<
                Where2<
                    Where<Current<STSalesTerritoryInqFilter.ownerID>, IsNotNull,
                        Or<Current<STSalesTerritoryInqFilter.territoryID>, IsNotNull,
                        Or<Current<STSalesTerritoryInqFilter.repID>, IsNotNull>>>, 
                    And<
                    Where2<
                        Where<Current<STSalesTerritoryInqFilter.ownerID>, IsNull,
                            Or<STSalesTerritory.ownerID, Equal<Current<STSalesTerritoryInqFilter.ownerID>>>>,
                        And<
                        Where2<
                            Where<Current<STSalesTerritoryInqFilter.territoryID>, IsNull,
                                Or<STSalesTerritory.territoryID, Equal<Current<STSalesTerritoryInqFilter.territoryID>>>>,
                            And<Where<Current<STSalesTerritoryInqFilter.repID>, IsNull,
                                Or<STSalesTerritory.repID, Equal<Current<STSalesTerritoryInqFilter.repID>>>>>>>>>>>>>>> 
        OpenSOOrders;

And this is the view with the action where the search doesnt work, and a PXSelect is needed to find the right document

        public PXSelectJoinGroupBy<
        Customer, 
        InnerJoin<Address, 
            On<Customer.defAddressID, Equal<Address.addressID>>, 
        InnerJoin<SOOrder, 
            On<Customer.bAccountID, Equal<SOOrder.customerID>>,
        InnerJoin<BAccount, 
            On<Customer.bAccountID, Equal<BAccount.bAccountID>>,
        InnerJoin<STSalesTerritory, 
            On<BAccountExt.usrTerritoryID, Equal<STSalesTerritory.territoryID>>>
            >>>, 
        Where2<
            Where<SOOrder.orderDate, GreaterEqual<Current<STSalesTerritoryInqDateFilter.startDate>>, 
                And<SOOrder.orderDate, LessEqual<Current<STSalesTerritoryInqDateFilter.endDate>>>>,
            And<
            Where2<
                Where<SOOrder.orderType, Equal<SOOrderTypeConstants.salesOrder>, 
                    Or<SOOrder.orderType, Equal<SOOrderTypeConstantsExt.websiteOrder>>>,
                And<
                Where2<
                    Where<SOOrder.status, NotEqual<SOOrderStatus.hold>, 
                        And<SOOrder.status, NotEqual<SOOrderStatus.cancelled>, 
                        And<SOOrder.status, NotEqual<SOOrderStatus.voided>, 
                        And<Customer.customerClassID, NotEqual<marketplaceCustomerClassID>
                    >>>>, 
                    And<
                    Where2<
                        Where<Current<STSalesTerritoryInqFilter.territoryID>, IsNull, 
                            Or<BAccountExt.usrTerritoryID, Equal<Current<STSalesTerritoryInqFilter.territoryID>>>>,
                        And<Where<Current<STSalesTerritoryInqFilter.ownerID>, IsNull, 
                            Or<STSalesTerritory.ownerID, Equal<Current<STSalesTerritoryInqFilter.ownerID>>>>>>>>>>>>, 
        Aggregate<
            GroupBy<Customer.acctCD>>, 
        OrderBy<SOOrder.orderDate.Desc>> 
        NewCustomers;
3
Can you show how your views are defined?Brian Stevens
@BrianStevens I added the view definitionswatsonST

3 Answers

0
votes

I am not sure I understand enough of what you are doing to be able to help, but I'll try.

The primary key of SOOrder is CompanyID, OrderType, OrderNbr - that means you should search for SOOrder by OrderType and OrderNbr. You did that in the "workaround" but not the first attempt.

If your grids return values and you just need to make the Order Nbr field a clickable link to the SOOrderEntry screen, add the field to the view (in the screen editor) under the grid's "Levels" section and then mark the OrderNbr field as AllowEdit = true to make it a clickable. Assuming you are showing the OrderNbr in the grid from the SOOrder table, the SOOrder DAC defines the primary graph of SOOrder as SOOrderEntry and will know how to redirect there for you.

If you really need to extract the current SOOrder from the view OpenSOOrders to manually redirect to the order, you access the "Current SOOrder" from the view (made possible by your grid setting "SyncPosition=true") via OpenSOOrders.Current. For example, you can find the current SOOrder, create an instance of the SOOrderEntry graph, and set the current SOOrder (Document) as follows:

SOOrder order = OpenSOOrders.Current;
SOOrderEntry graph = PXGraph.CreateInstance<SOOrderEntry>();
graph.Document.Current = order;

This should work because order is the exact record in the database. To search with just the order type and number, you would use:

graph.Document.Current = graph.Document.Search<SOOrder.orderType, SOOrder.orderNbr>
    (order.OrderType, order.OrderNbr);

For completeness, if SOOrder was being updated in a method that you are overriding, you would use Locate instead of Search. Search will find the record in the database, but Locate will find it in the cache. This means that if the method updated values then you will retrieve those updates rather than wiping them out with a fresh copy of the record that Search would retrieve. Locate uses the key fields of the specified record to locate the record in the cache as shown below.

graph.Document.Current = graph.Document.Locate(order);

As for the view not finding the current record for you, it seems you aggregating by Customer. I don't use aggregate often, but I belive this means the results will be returned summarized by customer. If there is more than 1 OrderNbr value, it cannot be shown in the aggregate. As the second view aggregates by Customer, you would need to allow the user to select orders of the customer and use Current from THAT view.

If you want your aggregate in 1 grid and have it drive a view of SOOrders of the selected customer, you would add a new view (and secondary grid) for SOOrder as follows:

public PXSelect<SOOrder,
    Where<SOOrder.customerID, Equals<Current<Customer.bAccountID>>>> CustomerOrders;

Just to put a plug in for FBQL, you could write that as:

public SelectFrom<SOOrder>
    .Where<SOOrder.customerID.IsEqual<Customer.bAccountID.FromCurrent>>
    .View CustomerOrders;

The SyncPosition on NewCustomers should cause CustomerOrders to refresh as you change rows of NewCustomers. Again, on this view, I would make the OrderNbr field of SOOrder a clickable link by using AllowEdit = true.

0
votes

I have encountered scenarios in pages with 2 primary keys where the Search<> is invoked as follows:

graph.Document.Search<SOOrder.orderNbr>(row.OrderNbr, row.OrderType);

There are multiple references in Acumatica's source code. A good example can be found in the SOInvoiceEntry graph >> RecalcUnbilledTax() method:

soOrderEntry.Document.Current = soOrderEntry.Document.Search<SOOrder.orderNbr>(order.SOOrderNbr, order.SOOrderType);
0
votes

Your second view has an aggregated selection, grouped by Customer.AcctCD. For the same customer you might have multiple orders: which one should be displayed and opened? By default, Acumatica generates the SQL with MAX for unspecified columns. I would try to take the aggregation out of the view and see if it works.