Sending sales order ack with specified FROM address

Domain/O365/Equivalent

1 Like

You may have to include a DMARC record too.

1 Like

I have the SendEmail code/function working but need some assistance with the SaveOrderAck function. I’ve only narrowed it down to somewhere in the GetASalesOrderPDF function. The only value I’ve modified is “ReportStyleNum = 1001”. Anything else obvious that I’m missing?

See the Postman response below.

1 Like

Looks like the exception occurs on soa.RunDirect(…)

1 Like

Okay I just re-tested this, looks like I had the “Required Transaction” checkbox checked on the SaveOrderAck function. Not sure why I checked that, I don’t have it checked in my production version. Try unchecking that box on the function.

That was it. Thanks for your time on this!

1 Like

Ok Kevin I’m getting some odd behavior on this. Looks like it’s related to the Epicor user that’s logged in.

When I run the code from the screenshot it processes correctly.

When another user runs the code the ordernum param is correct, the PDF file name is correct (and eventually attached to the email), but the actual report rendered within the PDF is of the wrong sales order. It’s actually always the same order, no matter which ordernum we send in to the function. Is this somehow related to permissions when calling soa.RunDirect() ? Or is this an issue with the Db.SysRptLst.Join code?

We do this using print routing and edit the from field. Just make sure the account used to send emails from epicor has permissions to send emails as the user user.
image

Hi Jason,

Are the users calling the SaveOrderAck function directly? Or are they using the EmailOrderAck function? I’m not seeing any ordernum hard coded there, and the “taskNote” string/guid variable is only generated in that delegate function, so I’m not sure how it could generate a sales order that is different that the ordernum used to save the file name.

Could you send a screencap of the System Monitor with the Sales Order Acknowledgment report task line when another user runs it?

Here’s a screenshot of the Reports list in System Monitor. There are two Sales Order Acknowledgements in the list. The highlighted record was for a user where it attached the SOA with the correct order in the PDF name, but the incorrect order in the SSRS report.

The next SOA on 12:51PM was one I generated which included the correct SSRS data/report.

Would it be possible to include an archive period so I could review the table generated in my ProductionReports database? Something like paramRow.ArchivePeriod = 1. Any idea what the attribute name is and what value to use for “Day”?

Looks like the attribute name could be “ArchiveCode” which expects an int for the value.

Looks like paramRow.ArchiveCode = 1 works. I’ve also reproduced the issue in my Pilot company with my own login. File name has correct order number, but the included SSRS report is the wrong order data.

I’m stumped on this. It uses the same orderNum parameter to pass to the report and name the file, so they should match. @klincecum any ideas?

I’m looking into the contents of the Db.SysRptList object and so far I know it has 18 rows. Maybe the .FirstOrDefault() is the issue? I’m going to iterate through the list to get more info about the rows.

I’d like to see the rows linked from systask and sysrptlist.

I went through something very similar a while back with doing this through a customization instead of a function but I think the same idea applies. Instead of doing the join to get the report bytes you can set up a loop to check when the report is finished generating. Also to note I’m setting the workstation id as the guid, similar to what you’re doing with the task note. Hopefully this helps!

This is what I have after RunDirect:

using(Ice.Proxy.BO.ReportMonitorImpl RM = WCFServiceSupport.CreateImpl<Ice.Proxy.BO.ReportMonitorImpl>(session, Epicor.ServiceModel.Channels.ImplBase<Ice.Contracts.ReportMonitorSvcContract>.UriPath))
				{
				int timer=0;
					
				byte[]report = null;
				bool morepages;
				SysRptLstListDataSet RptList;
				RptList = RM.GetList(@"WorkStationID ='"+workstationid+"'", 0, 0, out morepages);
			while (RptList.SysRptLstList.Count == 0 ) // setup a loop to look for when the report has been generated.
				{					
					System.Threading.Thread.Sleep(500);
					timer = timer + 1;
					if (timer > 100)
						{
							MessageBox.Show("Attempts to generate a OrderAck pdf has timed-out. Please try again.");
							return;
						}									
					RptList = RM.GetList(@"WorkStationID ='"+workstationid+"'", 0, 0, out morepages);
				}

					string tableguid;
					tableguid = RptList.SysRptLstList[0].FileName.Replace("REPORT DATABASE: ","");
					//byte[]report = null;
					Guid task =  RptList.SysRptLstList[0].SysRowID;
					report = RM.GetReportBytes(task);
				
				string path =Path.GetTempPath();
				File.WriteAllBytes(@path + "Order " + val.ToString()+".pdf",report);

Source:

I was out a few days and unable to work on this until today. I was able to verify that SSRS was actually processing the wrong report data by looking at the Report History/List in the Kinetic Task Monitor and opening the Sales Order Acknowledgment created via the function. I’m not sure how it decided which sales order to process, but it was always the same record.

I reviewed the function request in Developer Tools when using Generate Only and noticed a parameter named “OrderList” which is also set to the order number (string type). After including that parameter I’m now getting a consistent report result which references the correct order.

So do you all run into things like this often when working on customizations? How confident can I be that logic within standard functions is reliable?

image

Great job getting that to work! I’d say that particular quirk is more related to reports specifically than to functions. I’ve never run into that particular issue, and I’ve been using that function for a while (at least, the function I based that on). However, mine runs on a schedule with the orderNum coming from query results, so that may be why I never noticed it: I don’t have other users executing.

Sometimes it definitely takes some digging when creating customizations/functions/BPMs, especially when calling business objects. A lot of times it doesn’t, though.

I’d say that you can definitely be confident that the logic is reliable. The caveat is that sometimes the logic is more complex than it appears at first glance, and you run into things like this.

Thanks for your time and help with this Kevin.