Update Vendor Payment Method With BAQ

Hi all!
I am working on a BAQ to update all of our vendors to the same payment method. I first created an updateable BAQ that lists all the vendors with PMUID=0.

Next, I created a custom action in the BPM to update all the results rows.

I setup a dashboard to run the BAQ from, just in case I needed to. Ideally I would run it right from the BAQ designer.

Here is the custom code I am using to try to update the vendor table.

foreach (var ttResults_iterator in (from ttResults_Row in ttResults select ttResults_Row)) // for every line in the BAQ results do this stuff...
{
       using (Erp.Proxy.BO.VendorImpl mySvc =  Ice.Assemblies.ServiceRenderer.GetService<Erp.Proxy.BO.VendorImpl>(Db))
         {
         mySvc.ChangeVendPayMethod(5, dsVend);
         mySvc.Update(dsVend);
         }
}

My problem is that I don’t know how to identify dsVend as a vendor dataset instead of a tableset. Also, I am not sure about my service renderer. I just snagged the BO listed in the trace.

(Please don’t suggest to use the DMT. I know that is probably a great tool. I don’t have it.)

Thanks!
Nate

It mostly looks fine, 2 changes that I can see. The reference in service renderer needs changed, and before changing the PayMethod you have to get the vendor record first. The GetByID returns the dataset you need, change the myVendorNum variable as needed.

# code block
using ( Erp.Contracts.VendorSvcContract svc = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.VendorSvcContract>(Db))
{
    var dsVend = svc.GetByID(myVendorNum);
    svc.ChangeVendPayMethod(5, ref dsVend);
    svc.Update( ref dsVend );
}

Thank you for the reply. I added your modifications and the code compiled nicely. The custom action ran, and completed without error. However, the records do not get updated. Here are the changes I made based on your suggestions:

foreach (var ttResults_iterator in (from ttResults_Row in ttResults select ttResults_Row)) // for every line in the BAQ results do this stuff...
{
using ( Erp.Contracts.VendorSvcContract svc = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.VendorSvcContract>(Db))
  {
      var dsVend = svc.GetByID(ttResults_iterator.Vendor_VendorNum);
      svc.ChangeVendPayMethod(5, ref dsVend);
      svc.Update(ref dsVend );
  }
}

You might have to actually change the value on dsVend and then call ChangeVendPayMethod followed by setting RowMod = “U” and then call Update.

Sometimes the ChangeXXX require the dataset to actually have the change.

I would do that with an Update by Query widget, right?

Example:

image

You see how the change is made in code to dataset and then the Change… method is called.

foreach (var ttResults_iterator in (from ttResults_Row in ttResults select ttResults_Row)) // for every line in the BAQ results do this stuff...
{
using (Erp.Contracts.VendorSvcContract svc = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.VendorSvcContract>(Db))
  {
      var dsVend = svc.GetByID(ttResults_iterator.Vendor_VendorNum);
      ttResults_iterator.Vendor_PMUID = 5;
      svc.ChangeVendPayMethod(5, ref dsVend);
      ttResults_iterator.RowMod = "U";
      svc.Update(ref dsVend );
  }
}

This changes the values that are on screen in the BAQ results, but the update doesn’t seem to save them. When I run it in a dashboard, I see the values in the PMUID column change. If I click save, or multithread save, it doesn’t save the records or give an error. Refreshing the BAQ or dashboard shows that the records haven’t been changed.

No dont do it on ttResults do it on dsVend

foreach (var ttResults_iterator in (from ttResults_Row in ttResults select ttResults_Row)) // for every line in the BAQ results do this stuff...
{
using (Erp.Contracts.VendorSvcContract svc = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.VendorSvcContract>(Db))
  {
      var dsVend = svc.GetByID(ttResults_iterator.Vendor_VendorNum);
      dsVend.Vendor[0].PMUID = 5;
      svc.ChangeVendPayMethod(5, ref dsVend);
      dsVend.Vendor[0].RowMod = "U";
      svc.Update(ref dsVend );
  }
}

This is my attempt to “do it on dsVend”. :stuck_out_tongue: I get a server side error. Did I miss something?

Does this actually get you a record should this be Vendor_VendorID instead of Num?

EDIT
Nevermind it is vendorNum

Get by id wants an int. I tried with VendorID (nvarchar) first and got that error. I could try to convert from string to int. I think it gives the right record, because when I was updating ttResults, it changes the values for all the vendors in the BAQ results. At least, until the for is refreshed.

Yep it is the right record, whats your error? It looks all good to me. Is 5 Valid?

Try calling the ChangeVendPayMethod first, then change it in the dsVend and the row mod.

The trace shows that method should return a ds with a rowmod U and the changed PMUID so you shouldnt have to do it manually but worth a shot.

1 Like

Actually, set the rowmod to U first, then call the change method.

I just tested quickly, but running that method with no row mod does not change anything in the dataset. Setting the rowmod U before calling the method returns a ds with the changed PMUID.

I modified the codes as suggested to this:

foreach (var ttResults_iterator in (from ttResults_Row in ttResults select ttResults_Row)) // for every line in the BAQ results do this stuff...
{
using (Erp.Contracts.VendorSvcContract svc = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.VendorSvcContract>(Db))
  {
      var dsVend = svc.GetByID(ttResults_iterator.Vendor_VendorNum);
      svc.ChangeVendPayMethod(5, ref dsVend);
      dsVend.Vendor[0].PMUID = 5;
      dsVend.Vendor[0].RowMod = "U";
      svc.Update(ref dsVend );
  }
}

For clarity I will also attach the BAQ for you to play with.
FindNoPayMethods.baq (52.8 KB)


## System Information ##
==================

AppServer Connection: https://centralusdtpilot01.epicorsaas.com/SaaS512Pilot
Form Name: dashboard to set payment method to ap check
Customization Name: 
Menu ID: UD77
Software Version: 3.2.700.8

============

Server Side Exception

BPM runtime caught an unexpected exception of 'NullReferenceException' type.
See more info in the Inner Exception section of Exception Details.

Exception caught in: Epicor.ServiceModel

## Error Detail ##
============

##!Correlation ID:##!  59b080e3-6c74-4a21-b94a-22468075bcb9
##!Description:##!  BPM runtime caught an unexpected exception of 'NullReferenceException' type.
See more info in the Inner Exception section of Exception Details.
##!Program:##!  Erp.Services.BO.Vendor.dll
##!Method:##!  VendorBeforeUpdate
##!Line Number:##!  4295
##!Column Number:##!  13
##!Original Exception Type:##!  NullReferenceException

## Client Stack Trace ##
==================
   at Epicor.ServiceModel.Channels.ImplBase`1.ShouldRethrowNonRetryableException(Exception ex, DataSet[] dataSets)
   at Ice.Proxy.BO.DynamicQueryImpl.RunCustomAction(DynamicQueryDataSet queryDS, String actionID, DataSet queryResultDataset)
   at Ice.Adapters.DynamicQueryAdapter.<>c__DisplayClass43_0.<RunCustomAction>b__0(DataSet datasetToSend)
   at Ice.Adapters.DynamicQueryAdapter.ProcessUbaqMethod(String methodName, DataSet updatedDS, Func`2 methodExecutor, Boolean refreshQueryResultsDataset)
   at Ice.Adapters.DynamicQueryAdapter.RunCustomAction(DynamicQueryDataSet queryDS, String actionId, DataSet updatedDS, Boolean refreshQueryResultsDataset)

## Inner Exception ##
===============
Object reference not set to an instance of an object.

##  ##



5 is a valid PMUID.

I made this change. I get the same error I just posted above.

It should look like this. This works in my environment, if it does not in yours maybe there is a difference between 10.2.400 and 10.2.600.

foreach (var ttResults_iterator in (from ttResults_Row in ttResults select ttResults_Row)) // for every line in the BAQ results do this stuff...
{
       
		using (Erp.Contracts.VendorSvcContract svc = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.VendorSvcContract>(Db))
		  {
			  var dsVend = svc.GetByID(ttResults_iterator.Vendor_VendorNum);
			  dsVend.Vendor[0].RowMod = "U";
			  svc.ChangeVendPayMethod(5, ref dsVend);			 			  
			  svc.Update(ref dsVend );
		  }
         
}

Copied and pasted your exact code, and still get the same error. Am I missing a ‘using’ or something?

I removed the line:

dsVend.Vendor[0].RowMod = "U";

And the error went away. The action completes without any error, but it does not update the records. Am I calling this line incorrectly?

You shouldn’t need any using statements, just the reference to Erp.Contracts.BO.Vendor under assemblies in the BPM.

What results in the message do you get if you add these lines right after the get by id?

string msg = String.Format("VendorRowCount:{0}", dsVend.Vendor.Count().ToString());
          
            foreach ( var vendorRow in dsVend.Vendor )
            {
              msg += System.Environment.NewLine + String.Format("Vendor:{0} PMUID:{1} RowMod:{2}", vendorRow.VendorNum.ToString(), vendorRow.PMUID.ToString(), vendorRow.RowMod);
            }
          
          this.PublishInfoMessage(msg, Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual, "", "" );