Attach order acknowledgement to email in BPM

@gpayne - I am grateful for your help. The only thing I can’t reconcile is the Ice.Mail assembly… That does not appear to be the same as System.Net.Mail, which is in the link you provided. So I can’t find a way to create an attachment on the mail any other way besides providing a link to a directory where the file resides. I believe it’s probably very plausible to do it - but I can’t find a reference to show me what methods might be available for the Ice.Mail assembly. That’s the million dollar question for me. I have looked on EpicWeb hoping to find some manual and I am striking out.

Well, I found this. This seems to be what I’m asking.

I haven’t figured out how to get my bytes to a stream yet, but I suspect I can find that if I look hard also. Getting closer. Thanks again everyone who’s chimed in.

Hi @dr_dan , in the reportstyle you could put below parameter “ReportOptions”. This will automatically save the file into server folder under the user name.

then in your program you can attach the last file that has been dropped.

image

Basically, we done it in a way that when user press “Send Email” button in POForm, it will generate the poform and open a custom form showing the attachment, and provides user to type email body message and press button to send email.

but you could also use standard email option.

This is good to know also. At this point, I am already filling the body of the email because this is an “automated” email to update people that the order was changed. So I’m attaching the new acknowledgement for their reference. I can completely understand your use case and why you’d want to handle it the way you’re doing it. I will definitely keep this in mind.

It’s nearly functional. I did get some tests to email me with an attachment - however I have gotten stuck where I am trying to feed a GUID into the TaskNote and then look for that record in SysRptLst. My LINQ query just doesn’t find it. If I search for that GUID manually (by copy/paste a previous report into the LINQ query explicitly, it will return the bytes and email an attachment. But it won’t do it on the fly. Here’s what I got…

    //--------------------------------
    //    PRINT NEW ACKNOWLEDGMENT
    //---------------------------------
      Guid myGuid = Guid.NewGuid();    
      string taskNote = myGuid.ToString().ToUpper();
        
      var soa = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.SalesOrderAckSvcContract>(Db);
      Erp.Tablesets.SalesOrderAckTableset dsSOA = null;
      dsSOA = soa.GetNewParameters();
      dsSOA.SalesOrderAckParam[0].OrderNum = orderNum;
      dsSOA.SalesOrderAckParam[0].OrderList = orderNum.ToString();
      dsSOA.SalesOrderAckParam[0].AgentID = "SystemTaskAgent";
      dsSOA.SalesOrderAckParam[0].AutoAction = "SSRSPREVIEW";
      dsSOA.SalesOrderAckParam[0].ReportStyleNum = 1004;
      dsSOA.SalesOrderAckParam[0].ArchiveCode = 0;
      dsSOA.SalesOrderAckParam[0].DateFormat = "m/d/yyyy";
      dsSOA.SalesOrderAckParam[0].NumericFormat = ",.";
      dsSOA.SalesOrderAckParam[0].ReportCultureCode = "en-US";
      dsSOA.SalesOrderAckParam[0].ReportCurrencyCode = "USD";
      dsSOA.SalesOrderAckParam[0].SSRSRenderFormat = "PDF";
      dsSOA.SalesOrderAckParam[0].TaskNote = taskNote;
      soa.SubmitToAgent(dsSOA, "SystemTaskAgent", 0, 0, "Erp.UIRpt.SalesOrderAck");
      soa.Dispose();
    

    //--------------------------------
    //    ATTACH ACKNOWLEDGMENT
    //---------------------------------
      Dictionary<string, Stream> attachments = new Dictionary<string, Stream>();
      int t = 0;
      
      while (t < 10000) //<< 10 seconds. It should only take a few seconds for the report to be generated. If it takes more than 10 seconds, sucks to suck.
      {
        System.Threading.Thread.Sleep(100); // 1/10 of a second
        var getFile = (from mmf in Db.SysRptLst
                   join st in Db.SysTask on new {mmf.Company, mmf.SysTaskNum} equals new {st.Company, st.SysTaskNum}
                   where mmf.Company == callContextClient.CurrentCompany
                   && st.TaskNote == taskNote
                   && st.TaskStatus == "COMPLETE"
                   orderby mmf.RecSeq descending
                   select mmf.RptData).FirstOrDefault();
      
        if (getFile != null)
        {        
          string strFile = Convert.ToBase64String(getFile);
    
          byte[] pdfBytes = System.Convert.FromBase64String(strFile);
          MemoryStream pdfFile = new MemoryStream(pdfBytes);
          attachments.Add("Order " + orderNum.ToString() + " Updated Ack.pdf", pdfFile);
          break;
        }
        else
        {
          t += 100;
        }
      }
      
      
    //--------------------------------
    //    SEND EMAIL WITH ATTACHMENT
    //---------------------------------      
      if (attachments.Count > 0)
      {
        mailer.Send(message, attachments);
      }
      else 
      {
        mailer.Send(message);
      }
while (t < 10000) //<< 10 seconds. It should only take a few seconds for the report to be generated. If it takes more than 10 seconds, sucks to suck.

This is how the local System Monitor does this. (It polls more frequently in the beginning but then slows down over time, which I didn’t show here.)

Downloading SO Acknowledgement pdf programatically - ERP 10 - Epicor User Help Forum (epiusers.help)

I guess what I am not getting is that it doesn’t find the report… but it’s there. Am I doing something goofy or violating some rule where I can’t do this? The timer ends up elapsing and does not find an attachment, so I get the email with no attachment. It’s like it won’t find the one I am creating in the same block of code.

That’s why I sent you that link. There is a status on the SysTask table called TaskStatus. Keep checking it until it’s not ACTIVE. If it’s Complete, then go get your attachment. If it errors or cancelled then inform the user.

2 Likes

I suggest you go this route, doing this in a BPM is going to make the performance on this method abysmal. If you MUST go this way I would go with an asynchronous function call which takes all the parameters and does the work outside the current thread.

Adding a waiting loop to the report print in a server side BPM is just :nauseated_face: not good

4 Likes

Another … “better” approach might be to use Auto Print, or Run the Report using the Breaking and Routing Capabilities of the system to do the emailing for you.

So instead of doing the email in the BPM, you run the report and let the report do the emailing for you automaticaly.

2 Likes

New plan:
finish my BPM by sending the acknowledgment to the system agent.
Setup a new async BPM that fires when SysTask.TaskStatus changes to COMPLETE.
If it’s a report I sent (aka it has some signature in the TaskNote), then I’ll build the email and add the attachment.

The only reason I don’t want to go this route is it does not support HTML (at least not in my version).

1 Like

side note: is there a way to enable a standard directive and pass some info with it? Like a variable or something?

Pass information in CallContext

1 Like

Thanks. You might not know it, but I am slowly leveling up haha. And I try to pay it forward as much as I can.

2 Likes

What are you a Dr of ?

Those are just my initials. The nickname stuck from when I was a teenager.

1 Like

Hi dr_dan,

Were you able to get a working BPM that sends the Order Acknowledgement form? I am trying to automate that process, and I’m having an issue getting the report as a pdf attachment.

Yes and no.
I thought I had it working OK (I got it to work seemingly reliably) but at some point I realized it was not working every time. So I ended up disabling it and haven’t gotten back to it to figure out why it wouldn’t work reliably.

I don’t know if either of you are still looking for this, but since I was referencing @dr_dan 's post to refresh my memory I thought I would pop this in.

Your answer lies in using RunDirect, instead of SubmitToAgent. If you want it to run asynchronously, run it via a scheduled function, which you can schedule on the fly to run “Now”.

Here is the run direct example, which just so happens to be the same report :tada:

1 Like

I’ll have to circle back. I don’t know why I needed to have HTML formatting. I mean, just getting a plain text email with a file attachment would be much better than getting a pretty email with no email attachment. Why wouldn’t I want to use AutoPrint I guess now that I’m thinking about it?