Unable to Dispatch Requisition using ReqEntry Adapter

Keep in mind instantiating an adapter is now a separate class than the one existing in the ui/form.

Would I be able to call the methods I need in the form, without instantiating another Adapter? How would I do that?

I figured worst case I could just use GetByID to pull the dataset, but I’m still going over the Customization User Guide and trying to learn.

Worst case I may be able to do it in a BPM, but I had hoped to do it on the UI and refresh it there.

I think there are some examples here of tapping into a form adapter, but I’m not at my computer atm so I can’t show you. I will try if I get to one.

Example:

//Access a forms natively available adapter(s)
//you can find the name of the native adapter in a form by using the Form Event Wizard>Before Adapter Method to return a list of adapters in that form
var adapterInsp = ((InspProcessingAdapter)(this.csm.TransAdaptersHT["oTrans_inspAdapter"]));

So it looks like it is just calling the Update method on the reqAdapter, on the requisition screen,
but the Update method doesn’t allow me to pass anything into the method according to the adapter wizard. How would I go about updating those values?

You’ll update the dataset, which is carried by the adapter. This is different than passing in variables into a method

So here’s what I have attempted so far, I’m now getting the object reference is not set to an instance of an object. Am I even relatively close?

try
{
ReqAdapter adapterReq = (ReqAdapter)csm.TransAdaptersHT[“oTrans_adapter”];
adapterReq.BOConnect();
adapterReq.GetByID(“1”);
adapterReq.ReqData.ReqHead[0][“RowMod”] = “U”;
adapterReq.ReqData.ReqHead[0][“NextActionDesc”] = “Create PO”;
adapterReq.ReqData.ReqHead[0][“NextActionID”] = “PO”;
adapterReq.ReqData.ReqHead[0][“ReplyOption”] = “A”;
adapterReq.ReqData.ReqHead[0][“ReqUserId”] = “A”;
adapterReq.ReqData.ReqHead[0][“UD_SysRevID”] = string.Empty;

adapterReq.Update();
adapterReq.Dispose();

} catch (System.Exception ex)
{
ExceptionBox.Show(ex);
}

}

is that the name of the adapter in that form? I am curious, I am unfamiliar with the requisition BO entirely, but you’ll want to make sure the adapter is reference by name as it appears.

Secondly, I believe the adapter in the form is already connected, no need to call connect again.
GetByID looks correct, it’s really exactly the same as any other adapter after you make your reference to it. Also, don’t dispose of the adapter, since it’s being managed by the transaction object.

Here’s some example code where I used the native adapter, alongside custom ones that I instantiated.

private void InspectionProcessingEntryForm_BeforeToolClick(object sender, Ice.Lib.Framework.BeforeToolClickEventArgs args)
	{
		if(args.Tool.Key == "Disposition Misc. Receipt")
		{
			//launch special search to retrieve pending PO receipts by Donor Number
			object ret = ProcessCaller.InvokeAdapterMethod
						(oTrans.EpiBaseForm, "QuickSearchAdapter", "ShowQuickSearchForm", new object[] 
						{oTrans.EpiBaseForm, "SearchByDonor", true/* multi-select */, new DataTable() });
			  
			// user cancelled
			if (ret == null) return;			
			ArrayList list = (ArrayList)ret;			
			
			//Return type is a calculated field, which is PackNum + ~ + VendorID
			
			//Handle Multiple Pack Slips
			for(int i = 0; i<list.Count; i++)
			{
				string  pcPurPoint = string.Empty; 
				string pcPackSlip = string.Empty;
				int piVendorNum = 0;
				
				string value = list[i].ToString();
				char delimiter = '~';
				string[] substrings = value.Split(delimiter);
				//set variables, first index is pack slip, second index is vendor num
				pcPackSlip = substrings[0];
				piVendorNum = Convert.ToInt32(substrings[1]);				

				//Find PO Receipt Data by Donor Number as Pack Slip			
				adapterReceipt = new ReceiptAdapter(oTrans);
				adapterReceipt.BOConnect();
				
				var adapterInsp = ((InspProcessingAdapter)(this.csm.TransAdaptersHT["oTrans_inspAdapter"]));			
				
				//call a get by ID method and return all dtl within a specific pack slip
				bool result = adapterReceipt.GetByID(piVendorNum, "", pcPackSlip);
				if(result)
				{	
					//Find RcvDtl records that haven't been received yet (InspectionPending = false)
					
					//create list to store InspectionPending records line numbers
					List<int> inspPending = new List<int>();
					//Find RcvDtl records that haven't been received yet (InspectionPending = true)
					int index = 0;
					foreach(DataRow row in adapterReceipt.ReceiptData.RcvDtl)
					{
						if(adapterReceipt.ReceiptData.RcvDtl[index].InspectionPending)
						{
							inspPending.Add(adapterReceipt.ReceiptData.RcvDtl[index].PackLine);
						}
						index++;
					}
					//if no records waiting to be inspected, exit method
					if(inspPending.Count==0)
					{
						MessageBox.Show(string.Format("Pack {0} has no Inspection Pending Receipt Detail records.", pcPackSlip));
						return;
					}

					//copy list to array for easy index crawling
					int piPackLine = 0;
					int[] array = new int[inspPending.Count];
					inspPending.CopyTo(array);
					
					foreach(int line in array)
					{
						piPackLine = line;
						adapterInsp.GetReceiptByID(piVendorNum, "",pcPackSlip,piPackLine); 
						oTrans.NotifyAll();			
					}
		
					oTrans.NotifyAll();
					oTrans.NotifyAll(EpiTransaction.NotifyType.Initialize, edvporView);
					Erp.UI.Controls.Combos.InspectrCombo cmb = (Erp.UI.Controls.Combos.InspectrCombo)csm.GetNativeControlReference("fd9fe6a9-c62e-4a1e-86cf-57f55bb73815");
					cmb.Focus();
				}
				else 
					MessageBox.Show("Unable to find Pack Slip...");
				adapterReceipt.Dispose();
			}
		}
		if(args.Tool.Key == "Disposition Inventory Non-Conformance")
		{
		
			//launch special search by Donor Number to retreive any non-conformance lots associated. Return value is NonConf.TranID
			object ret = ProcessCaller.InvokeAdapterMethod
						(oTrans.EpiBaseForm, "QuickSearchAdapter", "ShowQuickSearchForm", new object[] 
						{oTrans.EpiBaseForm, "SearchNonConformByDonor", true/* multi-select */, new DataTable() });
			// user cancelled
			if (ret == null) return;		
			
			ArrayList list = (ArrayList)ret;		
			//Return value is NonConf.TranID
			//Add each returned value from list into a real adapter, then will pass dataset into a native adapter method			
			var adapterInsp = ((InspProcessingAdapter)(this.csm.TransAdaptersHT["oTrans_inspAdapter"])); //native adapter

			for(int i=0;i<list.Count;i++)
			{
				string value = list[i].ToString();
				int convertValue = Convert.ToInt32(value);

				adapterInsp.GetByID(convertValue);

				oTrans.NotifyAll();
				oTrans.NotifyAll(EpiTransaction.NotifyType.Initialize, edvinvView);
			}		
			oTrans.NotifyAll();
			oTrans.NotifyAll(EpiTransaction.NotifyType.Initialize, edvinvView);	
			Erp.UI.Controls.Combos.InspectrCombo cmb = (Erp.UI.Controls.Combos.InspectrCombo)csm.GetNativeControlReference("69eac31b-3e9c-4e3f-9962-45220b10f738");
			cmb.Focus();
		}
	}

It would also be good to know where your exception is being triggered. Try a MessageBox, not ExceptionBox. I don’t know if that’s even in there aynmore

I’ll check out some of your code and maybe figure out what’s happening with mine.
Right now I’m firing on a click event, but would like to fire it after a specific field change.

It runs, but seems like it clears some of the menu data, and doesn’t actually dispatch the requisition.

try
{

ReqAdapter adapterReq = ((ReqAdapter)(csm.TransAdaptersHT[“oTrans_reqAdapter”]));
adapterReq.BOConnect();
adapterReq.GetByID(1);
adapterReq.ReqData.ReqHead[0][“RowMod”] = “U”;
adapterReq.ReqData.ReqHead[0][“NextActionDesc”] = “Create PO”;
adapterReq.ReqData.ReqHead[0][“NextActionID”] = “PO”;
adapterReq.ReqData.ReqHead[0][“ReplyOption”] = “A”;
adapterReq.ReqData.ReqHead[0][“ReqUserId”] = “Aaron”;
//adapterReq.ReqData.ReqHead[0][“UD_SysRevID”] = “”;

bool updresult = adapterReq.Update();
MessageBox.Show("Update " + updresult.ToString());
adapterReq.Dispose();

} catch (System.Exception ex)
{
ExceptionBox.Show(ex);
}

}

You’ll want to follow the trace pretty closely especially on a form adapter. You’re on the right track

I feel like I’m getting close, but still no dice. Everything seems to run, but the Req still doesn’t seem to be dispatched, following based on the trace I initially posted.

try
{

//var adapterInsp = ((InspProcessingAdapter)(this.csm.TransAdaptersHT[“oTrans_inspAdapter”]));
ReqAdapter adapterReq = ((ReqAdapter)(csm.TransAdaptersHT[“oTrans_reqAdapter”]));
adapterReq.GetByID(1);

  int intId = 1;
  int reqNum = 1;
  string reqUserId = "Aaron";
  bool resetDispatch = true;
  bool dispatchReq = false;
  string dispatchId = "Aaron";
  string nextActionID = "PO";
  string dispIDList = string.Empty;
  string dispNmList = string.Empty;

  bool bndresult = adapterReq.BuildNextDispatcher(nextActionID, out dispIDList, out dispNmList);
  MessageBox.Show("Build next dispatch: "+bndresult.ToString());

adapterReq.ReqData.ReqHead[0][“RowMod”] = “U”;
adapterReq.ReqData.ReqHead[0][“NextActionDesc”] = “Create PO”;
adapterReq.ReqData.ReqHead[0][“NextActionID”] = “PO”;
adapterReq.ReqData.ReqHead[0][“ReplyOption”] = “A”;
adapterReq.ReqData.ReqHead[0][“ReqUserId”] = “Aaron”;
//adapterReq.ReqData.ReqHead[0][“UD_SysRevID”] = “”;

bool updresult = adapterReq.Update();
MessageBox.Show("Update " + updresult.ToString());

bool chkresult = adapterReq.CheckToDo(dispatchId);
MessageBox.Show("Check to do: "+chkresult.ToString());

adapterReq.RDMenuFlags(reqNum, reqUserId, out resetDispatch, out dispatchReq);

MessageBox.Show(“Ran!”);
oTrans.NotifyAll();

} catch (System.Exception ex)
{
ExceptionBox.Show(ex);
}

}

Sounds like a good time to take a break :wink:
Can that requisition even be dispatched? Maybe that test data needs to be refreshed

Yeah, I’m going to take a step back for today. I’m able to dispatch without a problem through the UI.

1 Like

I might be wrong, but don’t you need to use BeginEdit and EndEdit when you are setting the field values?

I’ll try that shortly, and see how it goes. Doing some digging this morning, it looks like once the req is dispatched, it goes into the ReqLog table. I didn’t see any methods that would let me insert a row into it, so I think it happens on the update method. I can see in the customization where I’m able to return a RegLog dataset with a GetList, but I’m not seeing any adapters or methods to actually create one.

I’ll try the begin edit and end edit, and then probably revisit the trace again. I looked into the chm files for the tables and Business Objects. Maybe I’ll find something!

Hi Aaron,
Did you ever get this to work? I am trying to do the same, putting a button to call the Req dispatch form on click event. I will appreciate any help on this.

Hi Guys!
I am trying to do the same thing. I have a dashboard with a UBAQ and BPM inside. If the user click a part number from my dashboard, and click the button, then a req is automatically created. The req detail line is created, and then I try to dispatch it, but nothing happens. I am not trying to use custom code widgets, just the BOs and methods.
Part of my approach: UBAQ to Create Requisition

Did anyone resolve this?

Hey guys, same problem here, trying to dispatch with an Epicor Function.

Any progress ?

Yeah, it wants 2 lines in your dataset before the update: the initial one without any changes and RowMod=“” and the second one with the changes and RowMod=“U”.

First, call the GetByID to get the full req dataset (in this case tsReq). Then copy the header and set the fields:

// copy header
var currentRow = tsReq.ReqHead[0];
var newRow = tsReq.ReqHead.NewRow();
BufferCopy.CopyExceptFor(currentRow, newRow, "");

// set fields for the new header
newRow["NextDispatcherID"] = "ApproverIDHere";
newRow["NextActionID"] = "APPR";
newRow["ReplyOption"] = "A";
newRow["ReqUserId"] = "RequestorIDHere";
newRow["RowMod"] = "U";

// add new header to tableset
tsReq.ReqHead.Add(newRow);   

Finally, call the Update. Worked for me.

@Dragos thx for your code,its work well.
i need to reject the po requsition with the same trick, could you please give any suggusstion

For some reason, I’ll join the chorus - has anyone got a successful dispatch working in practice?

To be specific, when I update the fields that others have (and that I saw in the trace), it does update, but it does not log the changes.

Also, the “To do list” is wrong. It’s still showing a previous action:

image

Compared to the Req itself:
image

So clearly I have not fully dispatched it.

I am baffled that there is not a method for dispatching in the Req BO.

EDIT: If it helps, let me rephrase this:

  • Is “Dispatching” nothing more than updating some fields in ReqHead?
  • Does it also involve writing to the log (even though that does not show in the trace)?
  • Are there other things involved that I can’t see?