Updatable Dashboard - Multiple fields from multiple tables

Hi Epicor Community,

I am trying to let our Service department manage multiple fields from the same updatable dashboard.
This is the first level subquery that will be used in the final upper subquery as is (without any aggregation) while linking with some other subqueries.

In this subquery, I need to make the following fields available for update:

1- A Custom field in Customer Table named SiteID
2- A Custom field in Customer Table named Software
3- A Custom field in Customer Table named Firmware
4- ResourceID in JobOpDtl
5- NeedBy and ShipBy dates in Orderdtl

Number 5 is easy, I have already done it before but the request came in to add 1-4 as well and I am stuck.
The reason is that so far I have been using this:

Essentially with this method, only one table is updatable. I think I might need using the BPM option but have no experience when it comes to updatable dashboards (I am familiar with MEthod and Data Directives and have working experience).

Could you kindly guide me toward the best direction?

The topic below will not address specifics of your issue but…
It still might give you some ideas on how an advanced BPM works

1 Like

Hi @bordway ,

When I switched to advanced UBAQ radio button and pasted the same code that was available in basic mode, I got this error:

Column ‘Company, QueryID, ControlID’ is constrained to be unique. Value ‘OurCompanyID, BAQID, ad65747e-d865-40c2-abe4-d59f8279860f’ is already present.

Any insights?

Sorry, without more detail, hard to know what is going on.

For now…
Just wondering if you have downloaded the ICE Tools User Guide? Had a chance to review any working examples within the documentation or topics on this site?

I remember being puzzled more than a few times as I worked on my first Advanced BPM Update (and that was one of the more basic examples). Just wasn’t exactly “intuitive” (to me) at first how everything was interacting.

From your original description and screenshot, it seems to me like you are trying to do “A LOT”. TBD if you’ll be able to do it all via Advanced BPM.

Sorry for the delay @bordway ,

I decided to try doing this in a simple example.
This is the BAQ:
image

One UD field in Customer table (SiteID_c) and two fields on OrderDtl table (NeedByDate and RequestDate).

First I checked the standard code for each one of these using a standard BPM in UBAQ. Here are the codes for each one:

OrderDtl update:

// <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", "SalesOrder"))
{
    var ttResultQuery = ttResults
        .Where(row => !string.IsNullOrEmpty(row.RowMod) && row.RowMod != "P");

    foreach (var ttResult in ttResultQuery)
    {
        var ds = new Erp.Tablesets.UpdExtSalesOrderTableset();

        // Query to object mapping
        {
            var OrderDtl = new Erp.Tablesets.OrderDtlRow
            {
                Company = Constants.CurrentCompany,
                NeedByDate = ttResult.OrderDtl_NeedByDate,
                //OpenLine = ttResult.OrderDtl_OpenLine,
                OrderLine = ttResult.OrderDtl_OrderLine,
                OrderNum = ttResult.OrderDtl_OrderNum,
                RequestDate = ttResult.OrderDtl_RequestDate,
            };

            ds.OrderDtl.Add(OrderDtl);

            var OrderHed = new Erp.Tablesets.OrderHedRow
            {
                Company = Constants.CurrentCompany,
                //CurrencyCode = ttResult.OrderHed_CurrencyCode,
                //ExchangeRate = ttResult.OrderHed_ExchangeRate,
                //NeedByDate = ttResult.OrderHed_NeedByDate,
                //OrderAmt = ttResult.OrderHed_OrderAmt,
                OrderNum = ttResult.OrderHed_OrderNum,
            };

            ds.OrderHed.Add(OrderHed);
        }

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

        ttResult.RowMod = "P";

        // Object to query mapping
        {
            var OrderDtl = ds.OrderDtl.FirstOrDefault(
                tableRow => tableRow.Company == Constants.CurrentCompany
                    && tableRow.OrderLine == ttResult.OrderDtl_OrderLine
                    && tableRow.OrderNum == ttResult.OrderDtl_OrderNum);
            if (OrderDtl == null)
            {
                OrderDtl = ds.OrderDtl.LastOrDefault();
            }

            var OrderHed = ds.OrderHed.FirstOrDefault(
                tableRow => tableRow.Company == Constants.CurrentCompany
                    && tableRow.OrderNum == ttResult.OrderHed_OrderNum);
            if (OrderHed == null)
            {
                OrderHed = ds.OrderHed.LastOrDefault();
            }

            if (OrderDtl != null)
            {
                ttResult.OrderDtl_NeedByDate = OrderDtl.NeedByDate;
                //ttResult.OrderDtl_OpenLine = OrderDtl.OpenLine;
                ttResult.OrderDtl_OrderLine = OrderDtl.OrderLine;
                ttResult.OrderDtl_OrderNum = OrderDtl.OrderNum;
                ttResult.OrderDtl_RequestDate = OrderDtl.RequestDate;
            }

            if (OrderHed != null)
            {
                //ttResult.OrderHed_CurrencyCode = OrderHed.CurrencyCode;
                //ttResult.OrderHed_ExchangeRate = OrderHed.ExchangeRate;
                //ttResult.OrderHed_NeedByDate = OrderHed.NeedByDate;
                //ttResult.OrderHed_OrderAmt = OrderHed.OrderAmt;
                ttResult.OrderHed_OrderNum = OrderHed.OrderNum;
            }
        }

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

var ttResultsForDelete = ttResults.Where(row => row.RowMod != "P").ToArray();

foreach (var ttResult in ttResultsForDelete){    ttResults.Remove(ttResult);}

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

Customer Update:

// <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", "Customer"))
{
    var ttResultQuery = ttResults
        .Where(row => !string.IsNullOrEmpty(row.RowMod) && row.RowMod != "P");

    foreach (var ttResult in ttResultQuery)
    {
    
    
         

        // Query to object mapping
        {
            var Customer = new Erp.Tablesets.CustomerRow
            {
                Company = ttResult.Customer_Company,
                CustNum = ttResult.Customer_CustNum,
            };
            
            

            Customer.SetUDField<System.String>("SiteID_c", ttResult.Customer_SiteID_c);

            dsCustomer.Customer.Add(Customer);
            
        }

        BOUpdErrorTableset boUpdateErrorsCustomer = updater.Update(ref dsCustomer);
        
        if (this.BpmDataFormIsPublished()) return;

        ttResult.RowMod = "P";

        // Object to query mapping
        {
            var Customer = dsCustomer.Customer.FirstOrDefault(
                tableRow => tableRow.Company == ttResult.Customer_Company
                    && tableRow.CustNum == ttResult.Customer_CustNum);
            if (Customer == null)
            {
                Customer = dsCustomer.Customer.LastOrDefault();
            }

            if (Customer != null)
            {
                ttResult.Customer_Company = Customer.Company;
                ttResult.Customer_CustNum = Customer.CustNum;
                ttResult.Customer_SiteID_c = Customer.UDField<System.String>("SiteID_c", throwIfNull:false);
            }
            
            //===================================================
            
             
        }

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

var ttResultsForDelete = ttResults.Where(row => row.RowMod != "P").ToArray();

foreach (var ttResult in ttResultsForDelete){    ttResults.Remove(ttResult);}

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

Then in the updated BAQ switched to the Advanced BPM update:

And then clicked on the BPM Directives Configuration and added two base processings and one custom code block under each that one of them contains the code for Customer Update and the other one for OrderDtl:

The problem is that after setting them up, although I do not get any error at any level, only the Base Processing that is order earlier (10,20,30,…) takes effect.
In other words, when I give the priority to Customer update, Customer table updates but OrderDtl does not, and when OrderDtl’s Base processing is prioritized, Customer table does not get updated…

I even tried clipping the last part of each code where the ttResult table gets cleared and see face this issue.
Just to emphasize UBAQ runs with no problem:

And after running, I get this:

image

Hi Shizar,

Stupid Question - have you tried moving these to a RunCustomAction
If you move them here and then try and do each one in turn - does this then work?

Thanks

Mark

Hi @gunny72 ,

I get this error after disabling the update BPMs and copying them to RunCustomCode section:

After a gazillion times of trying finally this worked for me:




// <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>




  var ttResultQuery = ttResults
      .Where(row => !string.IsNullOrEmpty(row.RowMod) && row.RowMod != "P");

  foreach (var ttResult in ttResultQuery)
  {
      var ds = new Erp.Tablesets.UpdExtSalesOrderTableset();
      var dsCustomer = new Erp.Tablesets.UpdExtCustomerTableset();
      // Query to object mapping
      {
          var OrderDtl = new Erp.Tablesets.OrderDtlRow
          {
              Company = Constants.CurrentCompany,
              NeedByDate = ttResult.OrderDtl_NeedByDate,
              //OpenLine = ttResult.OrderDtl_OpenLine,
              OrderLine = ttResult.OrderDtl_OrderLine,
              OrderNum = ttResult.OrderDtl_OrderNum,
              RequestDate = ttResult.OrderDtl_RequestDate,
          };

          ds.OrderDtl.Add(OrderDtl);

          var OrderHed = new Erp.Tablesets.OrderHedRow
          {
              Company = Constants.CurrentCompany,
              //CurrencyCode = ttResult.OrderHed_CurrencyCode,
              //ExchangeRate = ttResult.OrderHed_ExchangeRate,
              //NeedByDate = ttResult.OrderHed_NeedByDate,
              //OrderAmt = ttResult.OrderHed_OrderAmt,
              OrderNum = ttResult.OrderHed_OrderNum,
          };

          ds.OrderHed.Add(OrderHed);
          
          
          var Customer = new Erp.Tablesets.CustomerRow
          {
              Company = ttResult.Customer_Company,
              CustNum = ttResult.Customer_CustNum,
          };
          
          

          Customer.SetUDField<System.String>("SiteID_c", ttResult.Customer_SiteID_c);

          dsCustomer.Customer.Add(Customer);
      }

      using (var updater = this.getDataUpdater("Erp", "SalesOrder")) {
      BOUpdErrorTableset boUpdateErrors = updater.Update(ref ds);
      if (boUpdateErrors?.BOUpdError?.Count > 0)
      {
          ttErrors
              .AddRange(
                  boUpdateErrors.BOUpdError
                      .Select(
                          e => new ErrorsUbaqRow
                          {
                              TableName = e.TableName,
                              ErrorRowIdent = ttResult.RowIdent,
                              ErrorText = e.ErrorText,
                              ErrorType = e.ErrorType
                          }));
      }
      
      }
      using (var updater2 = this.getDataUpdater("Erp", "Customer")) {
      BOUpdErrorTableset boUpdateErrorsCustomer = updater2.Update(ref dsCustomer);
      if (boUpdateErrorsCustomer?.BOUpdError?.Count > 0)
      {
          ttErrors
              .AddRange(
                  boUpdateErrorsCustomer.BOUpdError
                      .Select(
                          e => new ErrorsUbaqRow
                          {
                              TableName = e.TableName,
                              ErrorRowIdent = ttResult.RowIdent,
                              ErrorText = e.ErrorText,
                              ErrorType = e.ErrorType
                          }));
      }
      
      }
      
      
      
      if (this.BpmDataFormIsPublished()) return;

      ttResult.RowMod = "P";

      // Object to query mapping
      {
          var OrderDtl = ds.OrderDtl.FirstOrDefault(
              tableRow => tableRow.Company == Constants.CurrentCompany
                  && tableRow.OrderLine == ttResult.OrderDtl_OrderLine
                  && tableRow.OrderNum == ttResult.OrderDtl_OrderNum);
          if (OrderDtl == null)
          {
              OrderDtl = ds.OrderDtl.LastOrDefault();
          }

          var OrderHed = ds.OrderHed.FirstOrDefault(
              tableRow => tableRow.Company == Constants.CurrentCompany
                  && tableRow.OrderNum == ttResult.OrderHed_OrderNum);
          if (OrderHed == null)
          {
              OrderHed = ds.OrderHed.LastOrDefault();
          }

          if (OrderDtl != null)
          {
              ttResult.OrderDtl_NeedByDate = OrderDtl.NeedByDate;
              //ttResult.OrderDtl_OpenLine = OrderDtl.OpenLine;
              ttResult.OrderDtl_OrderLine = OrderDtl.OrderLine;
              ttResult.OrderDtl_OrderNum = OrderDtl.OrderNum;
              ttResult.OrderDtl_RequestDate = OrderDtl.RequestDate;
          }

          if (OrderHed != null)
          {
              //ttResult.OrderHed_CurrencyCode = OrderHed.CurrencyCode;
              //ttResult.OrderHed_ExchangeRate = OrderHed.ExchangeRate;
              //ttResult.OrderHed_NeedByDate = OrderHed.NeedByDate;
              //ttResult.OrderHed_OrderAmt = OrderHed.OrderAmt;
              ttResult.OrderHed_OrderNum = OrderHed.OrderNum;
          }
          
          
          
          var Customer = dsCustomer.Customer.FirstOrDefault(
              tableRow => tableRow.Company == ttResult.Customer_Company
                  && tableRow.CustNum == ttResult.Customer_CustNum);
          if (Customer == null)
          {
              Customer = dsCustomer.Customer.LastOrDefault();
          }

          if (Customer != null)
          {
              ttResult.Customer_Company = Customer.Company;
              ttResult.Customer_CustNum = Customer.CustNum;
              ttResult.Customer_SiteID_c = Customer.UDField<System.String>("SiteID_c", throwIfNull:false);
          }
          
          
      }
      
      
      

      
  }


var ttResultsForDelete = ttResults.Where(row => row.RowMod != "P").ToArray();
foreach (var ttResult in ttResultsForDelete){    ttResults.Remove(ttResult);}
foreach (var ttResult in ttResults){    ttResult.RowMod = "";}









2 Likes