Updatable BAQ with Advanced BPM Update on multiple tables

I have an updatable BAQ which allows updating the requested by date and Need by date on Order Header, Order Line and Order Release and also allowing updating on the Job Required Due Date. I have written custom code to update all 4 tables but something is not working correctly after clicking update in BAQ Designer.

Field Editor

Updated Fields in Analyze Grid
image

Field after clicking update
image

The line release dates are writing to bothe the Order Line and Order release. How?

Here is my BAQ Method directive code. Any ideas what is going wrong?

try
{
    Erp.Contracts.SalesOrderSvcContract hSalesOrder = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.SalesOrderSvcContract>(Db);
    Erp.Contracts.JobEntrySvcContract hJobEntry = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.JobEntrySvcContract>(Db);
    callContextBpmData.Character01 += "--Start//n"; 
    
    if (hSalesOrder != null)
    { 
        callContextBpmData.Character01 += "--UpdateSalesOrder//n"; 
        var resultQuery = queryResultDataset.Results.Where(row => !string.IsNullOrEmpty(row.RowMod) && row.RowMod != "P");
        foreach (var ttResult in resultQuery)
        {
            Erp.Tablesets.UpdExtSalesOrderTableset ds = new Erp.Tablesets.UpdExtSalesOrderTableset();
            bool errorOccurred;
            
            {
              var OrderHed = new Erp.Tablesets.OrderHedRow
              {
                  Company = ttResult.OrderHed_Company,
                  NeedByDate = ttResult.OrderHed_NeedByDate,
                  OrderNum = ttResult.OrderHed_OrderNum,
                  RequestDate = ttResult.OrderHed_RequestDate,
              };
              
              ds.OrderHed.Add(OrderHed);
                        
              var OrderDtl = new Erp.Tablesets.OrderDtlRow
              {
                  Company = ttResult.OrderDtl_Company,
                  NeedByDate = ttResult.OrderDtl_NeedByDate,
                  OrderLine = ttResult.OrderDtl_OrderLine,
                  OrderNum = ttResult.OrderDtl_OrderNum,
                  RequestDate = ttResult.OrderDtl_RequestDate,
              };
    callContextBpmData.Character01 += "-" + OrderDtl.NeedByDate.ToString() +"/n"; 
    callContextBpmData.Character01 += "-" + OrderDtl.RequestDate.ToString() +"/n"; 
              
              ds.OrderDtl.Add(OrderDtl);
              
              var OrderRel = new Erp.Tablesets.OrderRelRow
              {
                  Company = ttResult.OrderRel_Company,
                  NeedByDate = ttResult.OrderRel_NeedByDate,
                  OrderLine = ttResult.OrderRel_OrderLine,
                  OrderNum = ttResult.OrderRel_OrderNum,
                  OrderRelNum = ttResult.OrderRel_OrderRelNum,
                  ReqDate = ttResult.OrderRel_ReqDate,
              };
    callContextBpmData.Character01 += "-" + OrderRel.NeedByDate.ToString() +"/n"; 
    callContextBpmData.Character01 += "-" + OrderRel.ReqDate.ToString() +"/n"; 
              
              ds.OrderRel.Add(OrderRel);
            }
        
            BOUpdErrorTableset boUpdateErrors = hSalesOrder.UpdateExt(ref ds, true, true, out errorOccurred);
            //BOUpdErrorTableset boUpdateErrors = hSalesOrder.UpdateExt(ref ds);

            if (errorOccurred && boUpdateErrors != null && boUpdateErrors.BOUpdError != null)
            {
                //this.PublishInfoMessage(boUpdateErrors.BOUpdError[0]["ErrorText"].ToString(),Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual,"","");
               // this.PublishInfoMessage(...,Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual,"","");
            }
            //ttResult.RowMod = "P";
            
            // Object to query mapping
            {
                var OrderDtl = ds.OrderDtl.FirstOrDefault(
                    tableRow => tableRow.Company == ttResult.OrderDtl_Company
                        && 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 == ttResult.OrderHed_Company
                        && tableRow.OrderNum == ttResult.OrderHed_OrderNum);
                if (OrderHed == null)
                {
                    OrderHed = ds.OrderHed.LastOrDefault();
                }
            
                var OrderRel = ds.OrderRel.FirstOrDefault(
                    tableRow => tableRow.Company == ttResult.OrderRel_Company
                        && tableRow.OrderLine == ttResult.OrderRel_OrderLine
                        && tableRow.OrderNum == ttResult.OrderRel_OrderNum
                        && tableRow.OrderRelNum == ttResult.OrderRel_OrderRelNum);
                if (OrderRel == null)
                {
                    OrderRel = ds.OrderRel.LastOrDefault();
                }
            
                if (OrderDtl != null)
                {
                    ttResult.OrderDtl_Company = OrderDtl.Company;
                    ttResult.OrderDtl_NeedByDate = OrderDtl.NeedByDate;
                    ttResult.OrderDtl_OrderLine = OrderDtl.OrderLine;
                    ttResult.OrderDtl_OrderNum = OrderDtl.OrderNum;
                    ttResult.OrderDtl_RequestDate = OrderDtl.RequestDate;
                }
            
                if (OrderHed != null)
                {
                    ttResult.OrderHed_Company = OrderHed.Company;
                    ttResult.OrderHed_NeedByDate = OrderHed.NeedByDate;
                    ttResult.OrderHed_OrderNum = OrderHed.OrderNum;
                    ttResult.OrderHed_RequestDate = OrderHed.RequestDate;
                }
            
                if (OrderRel != null)
                {
                    ttResult.OrderRel_Company = OrderRel.Company;
                    ttResult.OrderRel_NeedByDate = OrderRel.NeedByDate;
                    ttResult.OrderRel_OrderLine = OrderRel.OrderLine;
                    ttResult.OrderRel_OrderNum = OrderRel.OrderNum;
                    ttResult.OrderRel_OrderRelNum = OrderRel.OrderRelNum;
                    ttResult.OrderRel_ReqDate = OrderRel.ReqDate;
                }
            }

        }
                
    }
    
    if (hJobEntry != null)
    {
      callContextBpmData.Character01 += "--UpdateJobEntry//n"; 
      var resultQuery = queryResultDataset.Results.Where(row => !string.IsNullOrEmpty(row.RowMod) && row.RowMod != "P");
      foreach (var ttResult in resultQuery)
      {
        var ds = new Erp.Tablesets.UpdExtJobEntryTableset();
        bool errorOccurred;
        
        {
            var JobHead = new Erp.Tablesets.JobHeadRow
            {
                Company = ttResult.JobHead_Company,
                JobNum = ttResult.JobHead_JobNum,
                ReqDueDate = ttResult.JobHead_ReqDueDate,
            };

            ds.JobHead.Add(JobHead);
        }
        BOUpdErrorTableset boUpdateErrors = hJobEntry.UpdateExt(ref ds, true, true, out errorOccurred);

        if (errorOccurred && boUpdateErrors != null && boUpdateErrors.BOUpdError != null)
        {
            //this.PublishInfoMessage(boUpdateErrors.BOUpdError[0]["ErrorText"].ToString(),Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual,"","");
           // this.PublishInfoMessage(...,Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual,"","");
        }
        ttResult.RowMod = "P";
        
        // Object to query mapping
        {
            var JobHead = ds.JobHead.FirstOrDefault(
                tableRow => tableRow.Company == ttResult.JobHead_Company
                    && tableRow.JobNum == ttResult.JobHead_JobNum);
            if (JobHead == null)
            {
                JobHead = ds.JobHead.LastOrDefault();
            }

            if (JobHead != null)
            {
                ttResult.JobHead_Company = JobHead.Company;
                ttResult.JobHead_JobNum = JobHead.JobNum;
                ttResult.JobHead_ReqDueDate = JobHead.ReqDueDate;
            }
        }
      }
      
      
    }
    
    

    hSalesOrder.Dispose();
    hSalesOrder = null;
    hJobEntry.Dispose();
    hJobEntry = null;
    
}
catch
{
}

1 Like

Not sure what is going on here. I changed the updatable BAQ to use the default BPM Update processing. It is doing the same thing (order release dates are updated to both the line and release, so it wasn’t my custom code. Can anyone see anything wrong with my query?

BAQ

Update - General Properties

Update - Update Processing

Analyze grid

Upon review

  • Set RowMod = “U” on every row you intend to update
  • Mark BAQ row as processed (“P”) after successful updates
  • Use “\n” not “//n” in logs
  • Only write dates if they’re valid (avoid DateTime.MinValue)
  • Null-check services before Dispose()
  • Capture and publish BO update errors for fast diagnosis

Code is untested, this is a first pass review. Please verify the code and test.


try
{
    var hSalesOrder = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.SalesOrderSvcContract>(Db);
    var hJobEntry   = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.JobEntrySvcContract>(Db);

    callContextBpmData.Character01 = (callContextBpmData.Character01 ?? string.Empty) + "--Start\n";

    // Only work rows that are not processed and have a RowMod
    var resultQuery = queryResultDataset.Results.Where(r => !string.IsNullOrEmpty(r.RowMod) && r.RowMod != "P");

    foreach (var ttResult in resultQuery)
    {
        bool anySuccess = false;

        // -------------------------
        // Sales Order block
        // -------------------------
        if (hSalesOrder != null
            && (ttResult.OrderHed_OrderNum > 0 || ttResult.OrderDtl_OrderNum > 0 || ttResult.OrderRel_OrderNum > 0))
        {
            callContextBpmData.Character01 += "--UpdateSalesOrder\n";

            var dsSO = new Erp.Tablesets.UpdExtSalesOrderTableset();

            // OrderHed
            if (ttResult.OrderHed_OrderNum > 0)
            {
                var hed = new Erp.Tablesets.OrderHedRow();
                hed.Company  = ttResult.OrderHed_Company;
                hed.OrderNum = ttResult.OrderHed_OrderNum;

                if (ttResult.OrderHed_NeedByDate > DateTime.MinValue)   hed.NeedByDate   = ttResult.OrderHed_NeedByDate;
                if (ttResult.OrderHed_RequestDate > DateTime.MinValue)  hed.RequestDate  = ttResult.OrderHed_RequestDate;

                hed.RowMod = "U";
                dsSO.OrderHed.Add(hed);

                callContextBpmData.Character01 += "-Hed NeedBy: " + (hed.NeedByDate == DateTime.MinValue ? "n/a" : hed.NeedByDate.ToShortDateString()) + "\n";
                callContextBpmData.Character01 += "-Hed ReqBy : " + (hed.RequestDate == DateTime.MinValue ? "n/a" : hed.RequestDate.ToShortDateString()) + "\n";
            }

            // OrderDtl
            if (ttResult.OrderDtl_OrderNum > 0 && ttResult.OrderDtl_OrderLine > 0)
            {
                var dtl = new Erp.Tablesets.OrderDtlRow();
                dtl.Company   = ttResult.OrderDtl_Company;
                dtl.OrderNum  = ttResult.OrderDtl_OrderNum;
                dtl.OrderLine = ttResult.OrderDtl_OrderLine;

                if (ttResult.OrderDtl_NeedByDate > DateTime.MinValue)   dtl.NeedByDate   = ttResult.OrderDtl_NeedByDate;
                if (ttResult.OrderDtl_RequestDate > DateTime.MinValue)  dtl.RequestDate  = ttResult.OrderDtl_RequestDate;

                dtl.RowMod = "U";
                dsSO.OrderDtl.Add(dtl);

                callContextBpmData.Character01 += "-Dtl NeedBy: " + (dtl.NeedByDate == DateTime.MinValue ? "n/a" : dtl.NeedByDate.ToShortDateString()) + "\n";
                callContextBpmData.Character01 += "-Dtl ReqBy : " + (dtl.RequestDate == DateTime.MinValue ? "n/a" : dtl.RequestDate.ToShortDateString()) + "\n";
            }

            // OrderRel
            if (ttResult.OrderRel_OrderNum > 0 && ttResult.OrderRel_OrderLine > 0 && ttResult.OrderRel_OrderRelNum > 0)
            {
                var rel = new Erp.Tablesets.OrderRelRow();
                rel.Company     = ttResult.OrderRel_Company;
                rel.OrderNum    = ttResult.OrderRel_OrderNum;
                rel.OrderLine   = ttResult.OrderRel_OrderLine;
                rel.OrderRelNum = ttResult.OrderRel_OrderRelNum;

                if (ttResult.OrderRel_NeedByDate > DateTime.MinValue)   rel.NeedByDate   = ttResult.OrderRel_NeedByDate;
                if (ttResult.OrderRel_ReqDate    > DateTime.MinValue)   rel.ReqDate      = ttResult.OrderRel_ReqDate;

                rel.RowMod = "U";
                dsSO.OrderRel.Add(rel);

                callContextBpmData.Character01 += "-Rel NeedBy: " + (rel.NeedByDate == DateTime.MinValue ? "n/a" : rel.NeedByDate.ToShortDateString()) + "\n";
                callContextBpmData.Character01 += "-Rel ReqBy : " + (rel.ReqDate    == DateTime.MinValue ? "n/a" : rel.ReqDate.ToShortDateString()) + "\n";
            }

            // Only call UpdateExt if we actually queued a row
            if (dsSO.OrderHed.Count > 0 || dsSO.OrderDtl.Count > 0 || dsSO.OrderRel.Count > 0)
            {
                bool soError;
                BOUpdErrorTableset soErrs = hSalesOrder.UpdateExt(ref dsSO, true, true, out soError);

                if (soError && soErrs != null && soErrs.BOUpdError != null && soErrs.BOUpdError.Count > 0)
                {
                    string msg = Convert.ToString(soErrs.BOUpdError[0]["ErrorText"]);
                    this.PublishInfoMessage("SalesOrder.UpdateExt: " + msg,
                        Ice.Common.BusinessObjectMessageType.Error, Ice.Bpm.InfoMessageDisplayMode.Individual, "", "");
                    callContextBpmData.Character01 += "SO ERROR: " + msg + "\n";
                }
                else
                {
                    anySuccess = true;

                    // If you want to reflect back values, you can read from dsSO here.
                    // Not strictly required for date updates.
                }
            }
        }

        // -------------------------
        // Job block
        // -------------------------
        if (hJobEntry != null && !string.IsNullOrEmpty(ttResult.JobHead_JobNum))
        {
            callContextBpmData.Character01 += "--UpdateJobEntry\n";

            var dsJob = new Erp.Tablesets.UpdExtJobEntryTableset();

            var jh = new Erp.Tablesets.JobHeadRow();
            jh.Company = ttResult.JobHead_Company;
            jh.JobNum  = ttResult.JobHead_JobNum;

            if (ttResult.JobHead_ReqDueDate > DateTime.MinValue) jh.ReqDueDate = ttResult.JobHead_ReqDueDate;

            jh.RowMod = "U";
            dsJob.JobHead.Add(jh);

            callContextBpmData.Character01 += "-Job ReqDue: " + (jh.ReqDueDate == DateTime.MinValue ? "n/a" : jh.ReqDueDate.ToShortDateString()) + "\n";

            bool jobError;
            BOUpdErrorTableset jobErrs = hJobEntry.UpdateExt(ref dsJob, true, true, out jobError);

            if (jobError && jobErrs != null && jobErrs.BOUpdError != null && jobErrs.BOUpdError.Count > 0)
            {
                string msg = Convert.ToString(jobErrs.BOUpdError[0]["ErrorText"]);
                this.PublishInfoMessage("JobEntry.UpdateExt: " + msg,
                    Ice.Common.BusinessObjectMessageType.Error, Ice.Bpm.InfoMessageDisplayMode.Individual, "", "");
                callContextBpmData.Character01 += "JOB ERROR: " + msg + "\n";
            }
            else
            {
                anySuccess = true;
            }
        }

        // Mark BAQ row as processed if at least one update succeeded
        if (anySuccess)
        {
            ttResult.RowMod = "P";
        }
    }

    // Clean up safely
    if (hSalesOrder != null) { hSalesOrder.Dispose(); hSalesOrder = null; }
    if (hJobEntry   != null) { hJobEntry.Dispose();   hJobEntry   = null; }
}
catch (Exception ex)
{
    // Bubble a hint to the user and keep trace in Character
    this.PublishInfoMessage("BAQ BPM error: " + ex.Message,
        Ice.Common.BusinessObjectMessageType.Error, Ice.Bpm.InfoMessageDisplayMode.Individual, "", "");
    callContextBpmData.Character01 = (callContextBpmData.Character01 ?? string.Empty) + "FATAL: " + ex.ToString() + "\n";
}
1 Like

Thanks for the suggestions. Most of those I had already cleaned up on my own.

I moved from TEST to our PILOT system and wrote a simple BAQ with only the OrderHed, OrderDtl and OrderRel tables. Then made the RequestDate and NeedByDates updatable at all three levels, using the builtin code, no custom code. Same results, the dates from the release get updated to both the Line and Release fields. Any ideas?

Here is an export of my latest simplified BAQ that is doing the same thing.
vawTest1030.baq (31.1 KB)