Противоречивый поиск в представлении данных при перенаправлении?

#acumatica

#acumatica

Вопрос:

У меня есть пользовательский график с несколькими сетками на разных вкладках. В каждой таблице есть столбец для номеров заказов на продажу, которые перенаправляют действия на график SOOrderEntry. Одна из сеток использует действие с этим кодом для поиска и вставки заказа на продажу в перенаправленный график, и это работает нормально:

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

Однако использование того же кода в действии для другой сетки не работает. Пошаговое выполнение отладчика показывает, что

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

возвращает пустой результат.

Для каждого действия в источнике данных pages установлено значение DependOnGrid=true, для каждой сетки установлено значение SyncPosition=true. Даже при жестком кодировании порядкового номера строки в параметр поиска он возвращает пустой результат.

Обходной путь, который я нашел для работы, заключается в использовании

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

в действиях, которые не работают.

Кто-нибудь сталкивался с этим или, может быть, имеет некоторое представление о том, что здесь происходит? Мне странно, что очень похожие действия перенаправления в одном и том же графике требуют другого кода для правильной работы.

Редактировать: добавление определений представления

Это представление, которое использует действие с поиском для поиска нужного документа.

         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;
  

И это представление с действием, в котором поиск не работает, и для поиска нужного документа требуется PXSelect

         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;
  

Комментарии:

1. Можете ли вы показать, как определяются ваши представления?

2. @BrianStevens Я добавил определения представлений

Ответ №1:

Я не уверен, что достаточно понимаю, что вы делаете, чтобы иметь возможность помочь, но я постараюсь.

Первичным ключом SOOrder является CompanyID, OrderType, OrderNbr — это означает, что вы должны искать SOOrder по OrderType и OrderNbr. Вы сделали это в «обходном пути», но не с первой попытки.

Если ваши сетки возвращают значения, и вам просто нужно сделать поле Order Nbr доступной для просмотра ссылкой на экран SOOrderEntry, добавьте поле в представление (в редакторе экрана) в разделе «Уровни» сетки, а затем отметьте поле ordern br как AllowEdit = true, чтобы сделать его доступным для просмотра. Предполагая, что вы показываете ORDERBR в таблице из таблицы SOOrder, SOOrder DAC определяет основной график SOOrder как SOOrderEntry и будет знать, как перенаправить его для вас.

Если вам действительно нужно извлечь текущий SOOrder из представления OpenSOOrders, чтобы вручную перенаправить на заказ, вы получаете доступ к «Текущему SOOrder» из представления (что стало возможным благодаря настройке сетки «SyncPosition = true») через OpenSOOrders.Current . Например, вы можете найти текущий SOOrder, создать экземпляр графика SOOrderEntry и задать текущий SOOrder (документ) следующим образом:

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

Это должно сработать, потому что order — это точная запись в базе данных. Для поиска только по типу и номеру заказа вы бы использовали:

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

Для полноты картины, если SOOrder обновлялся в переопределяемом вами методе, вы бы использовали Locate вместо Search . Поиск найдет запись в базе данных, но Locate найдет ее в кэше. Это означает, что если метод обновил значения, вы получите эти обновления, а не удалите их с помощью новой копии записи, которую извлек бы поиск. Locate использует ключевые поля указанной записи для поиска записи в кэше, как показано ниже.

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

Что касается представления, которое не находит для вас текущую запись, кажется, вы агрегируете по клиенту. Я не часто использую aggregate, но я полагаю, что это означает, что результаты будут возвращены в обобщенном виде клиентом. Если имеется более 1 значения OrderNbr, оно не может быть показано в совокупности. Поскольку второе представление агрегируется по клиенту, вам нужно будет разрешить пользователю выбирать заказы клиента и использовать текущие из ЭТОГО представления.

Если вы хотите, чтобы ваш агрегат был в 1 сетке и отображал просмотр заказов выбранного клиента, вы должны добавить новое представление (и дополнительную сетку) для заказа следующим образом:

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

Просто чтобы вставить плагин для FBQL, вы могли бы написать это как:

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

Синхронизация для новых клиентов должна приводить к обновлению CustomerOrders при изменении строк новых клиентов. Опять же, в этом представлении я бы сделал поле OrderNbr SOOrder доступной для просмотра ссылкой, используя AllowEdit = true .

Ответ №2:

Я сталкивался со сценариями на страницах с 2 первичными ключами, где поиск <> вызывается следующим образом:

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

В исходном коде Acumatica есть несколько ссылок. Хороший пример можно найти в SOInvoiceEntry graph >> Метод RecallUnbilledTax():

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

Ответ №3:

Ваше второе представление содержит агрегированный выбор, сгруппированный по клиенту.AcctCD. Для одного и того же клиента у вас может быть несколько заказов: какой из них следует отобразить и открыть? По умолчанию Acumatica генерирует SQL с максимальным значением для неопределенных столбцов. Я бы попытался удалить агрегацию из представления и посмотреть, работает ли она.