BPM Method on SSRS Email (print) a Sales Order?

When our users are done entering a sales order they want to send a order acknowledgement via email. We want to use the standard SSRS email option under the Print menu (see screen shot) but pre-filled in Subject, To, and email Body.

I’ve done a trace but the method it shows can’t be found. Any ideas where to look?

Trace snip:
< tracePacket >
< businessObject>Erp.Proxy.Rpt.SalesOrderAckImpl< /businessObject>
< methodName>SubmitToAgent< /methodName>

Screen shot:

2 Likes

Was trying another route of using AutoPrint. Can variables be referenced in a auto print email message? I get an error when I try to use the variable I have setup for the customer’s email address.

Here’s an example of a BPM sending SSRS email via the standard method in C# for PO Print using the SSRS Print to Email Option

var poForm = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.POFormSvcContract>(Db);
POFormTableset pofTS = poForm.GetNewParameters();
    POFormParamRow r = pofTS.POFormParam[0];
    r.PONum = ttrecord.PONum;
    r.BuyerID = "";
    r.POList = "";
    r.BuyerList = "";
    r.SysRowID = Guid.Parse("00000000-0000-0000-0000-000000000000");
    r.AutoAction = "SSRSPrint";
    r.PrinterName = "NoPrinting";
    r.AgentSchedNum = 0;
    r.AgentID = "SystemTaskAgent";
    r.AgentTaskNum = 0;
    r.RecurringTask = false;
    r.RptPageSettings = "";
    r.RptPrinterSettings = "";
    r.RptVersion = "";
    r.ReportStyleNum = 1003;
    r.WorkstationID = "";
    r.TaskNote = "";
    r.ArchiveCode = 0;
    r.DateFormat = "m/d/yyyy";
    r.NumericFormat = ",.";
    r.AgentCompareString = "";
    r.ProcessID = "";
    r.ProcessTaskNum = 0;
    r.DecimalsGeneral = 0;
    r.DecimalsCost = 0;
    r.DecimalsPrice = 0;
    r.GlbDecimalsGeneral = 0;
    r.GlbDecimalsCost = 0;
    r.GlbDecimalsPrice = 0;
    r.FaxSubject = string.Format("PO: {0} contains a requisition which you requested / approved. The PO has been approved and issued to the vendor", ttrecord.PONum); ;
    r.FaxTo = "";
    r.FaxNumber = "";
    r.EMailTo = "emailto@email.com"
    r.EMailBody = emailBody.ToString();
		
    r.AttachmentType = "PDF";
    r.ReportCurrencyCode = "USD";
    r.ReportCultureCode = "en-US";
    r.SSRSRenderFormat = "PDF";
    r.RowMod = "A";
    poForm.RunDirect(pofTS);
6 Likes

Thanks Jose,

I’m still using the standard BPM C# tool for code. Is there a way to lookup what the SOForm parameters are or is the best way to use visual studio?

The SOForm parameters you can see in a trace when you print it.

1 Like

Thanks again sir!

I’m downloading Visual Studio 2015 from microsoft now as well, hopefully it’ll make my life easier and I can learn more coding and be more helpful around here answering questions instead of asking them.

1 Like

Ok, I’m close. Just a few error I can’t seem to figure out. Looks like an assembly but I’m not sure how to add it or what it is. Running a new trace log to see if it’ll help.

This is BPM so you should use TableSets not DataSets look at my Example

Also your GetService should be

GetService<Erp.Contracts.SalesOrderAckSvcContract>(Db)

Thanks for the correction. Guess I pulled too much out of the tracelog as I got both from the trace. Still missing something, I think it’s a reference but I’ve added the ones I think it’d need, am I missing some?

System.Drawing.Bitmap CS0246 The type or namespace name ‘SalesOrderAckTableSet’ could not be found (are you missing a using directive or an assembly reference?)

System.Drawing.Bitmap CS0246 The type or namespace name ‘SOFormParamRow’ could not be found (are you missing a using directive or an assembly reference?)

image

Hi Randy,

Can you share the code for this? I’d like to see if I can get it going on my side as well.

I attacked a similar idea in a different way. We purchased “SSRS Advanced Routing/Breaking” module recently so I’m using that to generate the print. So my BPM checks for the correct conditions on when to fire and then i’m using the “Auto Print” widget to send the print job over to SSRS Routing/Breaking.

If I generate a print from the BPM “Custom Code”, then I may not need to use the “Auto Print” widget to hand the print over to SSRS Routing/Breaking to generate the document. It may save a step. However, if I stick with the current method, I wouldn’t need to write any custom code! Decisions! :slight_smile:

Ideally, I want to print a BAQReport from the custom code but I’m not very well versed in C# so that will have to happen another time!

Thanks,
Josh

You’ll need to add the right using statement

using Erp.Tablesets;

And it should be SalesOrderAckParamRow

1 Like

Hmm, still getting errors.

Looks like it may be a UI customization that a BPM can’t do according to a EUG forum post.

“UI Customisation, not possible in a BPM…”

https://www.epicorusers.org/communities/community-home/digestviewer/viewthread?MessageKey=12c3ed1e-1cb7-4cac-8430-a687648662b3&CommunityKey=df2aacd6-d4fd-42fc-850f-eea2bb5eef97&tab=digestviewer

For the most part it’s a copy of Jose’s example and you may have more luck as you have the extra module.

I put this as a data directive, for some reason it works there.

Make sure the Assemblies has Erp.Contracts.Rpt.SalesOrderAck

Here is the code:

var reportParamTS = new Erp.Tablesets.SalesOrderAckTableset();
var reportParamRow = new Erp.Tablesets.SalesOrderAckParamRow();
reportParamTS.SalesOrderAckParam.Add(reportParamRow);

int rowIndex = 0;


var primaryTableRow = ttOrderHed.Where(tt=>tt.Updated()).FirstOrDefault();
	
if(primaryTableRow != null)
{
	reportParamRow.OrderNum = primaryTableRow.OrderNum;
	reportParamRow.ArchiveCode = Convert.ToInt32("0");
	reportParamRow.PrintReportParameters = Convert.ToBoolean("False");
	reportParamRow.SSRSEnableRouting = Convert.ToBoolean("False");
	
	reportParamRow.AutoAction =  "SSRSPrint" ;
	reportParamRow.ReportStyleNum = 2 ;
	reportParamRow.WorkstationID = "MYWorkStation";
	reportParamRow.TaskNote = "";
	
	if (reportParamTS.SalesOrderAckParam.Columns.Contains("EmailTo"))
	{
		reportParamRow.FaxTo = "";
		reportParamRow.FaxNumber = "";
	reportParamRow.FaxSubject = "The order " + primaryTableRow.OrderNum + " has been created from PO: " + primaryTableRow.PONum;
		reportParamRow.EMailTo = "testemail@yyy.net";
		reportParamRow.EMailCC = "";
		reportParamRow.EMailBCC = "";
		reportParamRow.EMailBody = "Please see the attached sales acknowledgement for order " + primaryTableRow.OrderNum + " which was created from PO: " + primaryTableRow.PONum;
		reportParamRow.AttachmentType = "PDF";
	}
	
	// Run immediately
	try
	{
	reportParamRow.AgentID = ""; /* Clear the Agent fields when running direct */
	reportParamRow.AgentSchedNum = 0;
	reportParamRow.AgentTaskNum = 0;

	// Using this method will not block the thread
	object[] outParam = null;
	Ice.Hosting.ServiceCaller.Execute("Erp:Rpt:SalesOrderAck", "WriteSysTask", new System.Collections.Specialized.NameValueCollection(), new object[]{reportParamRow}, out outParam);
	int sysTaskNum = Convert.ToInt32(outParam[0]);

	// Decrypt the password
	var password = Epicor.Security.Cryptography.Encryptor.DecryptToString(  "Your Encrypted Password"  );	

	// Create the TaskLauncher instance.
	var taskLauncher = new Ice.Hosting.TaskLauncher();
	System.Threading.Tasks.Task launchingTask = new System.Threading.Tasks.Task(() => {taskLauncher.CallTask( "manager" , password, sysTaskNum);});
	launchingTask.Start();


	}
	catch (Exception ex)
	{
	
	}
	rowIndex++;	
        	
 }
2 Likes

Ah ha! I wasn’t declaring the variables! I did mention I’m not a coder, right? Which is why I knew it was something stupid and easy I was missing.

Looking over your code I can tell there is much more I was missing, like converting the data types (Boolean, etc) and everything from your “Run immediately” line.

I wish I could give more than one Solution checkbox both you and Jose deserve one!

Code doesn’t error and the BPM fires, but no emails so I guess we do need the “SSRS Advanced Routing/Breaking” module.

You do not need that for this can you post all your code?

Jos? C Gomez
Senior Software Engineer

This is bpm code not a customization and it does work on bpm.
Post your code

Jos? C Gomez
Senior Software Engineer

I appreciate the help guys I feel bad for not getting this going myself. The code is pretty much a copy/paste of Ken’s. I’ve verified the report style ID, Epi User/Pass (I’m using a “system agent” one we have not “manager”.

var reportParamTS = new Erp.Tablesets.SalesOrderAckTableset();
var reportParamRow = new Erp.Tablesets.SalesOrderAckParamRow();
reportParamTS.SalesOrderAckParam.Add(reportParamRow);

int rowIndex = 0;

var primaryTableRow = ttOrderHed.Where(tt=>tt.Updated()).FirstOrDefault();
    
if(primaryTableRow != null)
{
    reportParamRow.OrderNum = primaryTableRow.OrderNum; 
    reportParamRow.ArchiveCode = Convert.ToInt32("0");
    reportParamRow.PrintReportParameters = Convert.ToBoolean("False");
    reportParamRow.SSRSEnableRouting = Convert.ToBoolean("False");  
    reportParamRow.AutoAction =  "SSRSPrint" ;
    reportParamRow.ReportStyleNum = 1002 ;   // Our StyleID 
    reportParamRow.WorkstationID = "MYWorkStation";
    reportParamRow.TaskNote = "SO_Ack";
    
//    if (reportParamTS.SalesOrderAckParam.Columns.Contains("EmailTo"))
//    {
        reportParamRow.FaxTo = "";
        reportParamRow.FaxNumber = "";
        reportParamRow.FaxSubject = "The order " + primaryTableRow.OrderNum + " has been created from PO: " + primaryTableRow.PONum;
        reportParamRow.EMailTo = CustEmail;  // BPM variable 
        reportParamRow.EMailCC = "";
        reportParamRow.EMailBCC = "";
        reportParamRow.EMailBody = "Please see the attached sales acknowledgement for order " + primaryTableRow.OrderNum + " which was created from PO: " + primaryTableRow.PONum;
        reportParamRow.AttachmentType = "PDF";
        reportParamRow.RowMod = "A";
        reportParamRow.SSRSRenderFormat = "PDF";
//    }
    
    // Run immediately
    try
    {
    reportParamRow.AgentID = ""; /* Clear the Agent fields when running direct */
    reportParamRow.AgentSchedNum = 0;
    reportParamRow.AgentTaskNum = 0;

    // Using this method will not block the thread
    object[] outParam = null;
    Ice.Hosting.ServiceCaller.Execute("Erp:Rpt:SalesOrderAck", "WriteSysTask", new System.Collections.Specialized.NameValueCollection(), new object[]{reportParamRow}, out outParam);
    int sysTaskNum = Convert.ToInt32(outParam[0]);

    // Decrypt the password
    var password = Epicor.Security.Cryptography.Encryptor.DecryptToString( "ThePaswordHere" );    

    // Create the TaskLauncher instance.
    var taskLauncher = new Ice.Hosting.TaskLauncher();
    System.Threading.Tasks.Task launchingTask = new System.Threading.Tasks.Task(() => {taskLauncher.CallTask( "EpiUserNameHere" , password, sysTaskNum);});   
    launchingTask.Start();
    }
    catch (Exception ex)
    {  
    }
    rowIndex++;              
 }

I’m having my own issues with the Advanced Routing/Breaking so don’t feel bad.

Thank you for posting and also thanks to those who are helping to get this going. You are helping us both out by adding to this.

My code is for a Data Directive. not the Method directive.

There might be a few differences running from the server vs. client.

Does your code work if you hard code an email. Just to make sure that is working? Are there tasks in the system monitor? Are there errors there?