BPM that emails a report attachment - Vantage 8

Good morning,

I’ve recently run into the request of creating a BPM in Vantage 8 that sends an email that has an attached report. Is this even possible in Vantage 8? I know 9 and 10 can do this, but does 8 have the capability? Any ancient Progress code out there for something like this? Finding the event and creating code to send the email is one thing, but printing a report and then attaching it to that email is quite another.

I appreciate any insights.

In V8, a BAM (Business Activity Monitor - which is now a Data Directive in E10), can be setup to generate an email on the change of a table field. The best example is a Shipping notice, that sends an email when the ShipHead.Status goes from OPEN to SHIPPED (I’m paraphrasing the table, fields and values).

An email can be generated in a BPM but it will take custom code. I might have had one. If I can find the code, I’ll post it.

Here’s some old code for a Shipping notice in V8

BTW - It actually generates HTML based message.

/* Finshed: 2/12/16 */

/* 2/13/2016 CRK
 - Added displaying open items 
 
    2/16/16 CRK
 - Added code to fix (tm) char
 
    2/18/16 CRK
 - added To and CC emails to body text
 
    2/21/16  CRK
 - added function for converting odd characters

    2/23/16  CRK
 - Fixed part desc

    2/24/16  CRK
 - added Silvia Laemmle (<slaemmle@XXXXXX.com>) to CC list

    3/19/16  CRK
 - added Lisa Porter (<slporter@XXXXXX.com>) to CC list
 
    6/1/16 CRK
- Added checks for FIND FIRST calls to see if record is available, before using it.
- Using input param 'Email-CC' as initial list of for people to be CC'd.  
  In the future, just update the CC: list in the BAM, instead of this code.

	9/14/16 CRK
- Fixed "Ship TO name".  Was displaying Customer.Name
***************************/

FUNCTION foo RETURNS CHARACTER (s AS CHARACTER):
  s = REPLACE(s, ">", "&gt;").
  s = REPLACE(s, "<", "&lt;").
  s = REPLACE(s, CHR(49833), "&copy;").
  s = REPLACE(s, CHR(49838), "&reg;").
  s = REPLACE(s, CHR(14844060),CHR(34)).
  s = REPLACE(s, CHR(14844061),CHR(34)).
  s = REPLACE(s, CHR(14845090), "&trade;").
  s = REPLACE(s, CHR(14844588), "&euro;").
  RETURN s.
END.


{ud/GlbAlert.i &TableName = "ShipHead"}
DEFINE VARIABLE NewEmailBody AS CHARACTER NO-UNDO.
DEFINE VARIABLE tn AS CHARACTER NO-UNDO.
DEFINE VARIABLE ordNum as INTEGER NO-UNDO.
DEFINE VARIABLE ordCount as INTEGER NO-UNDO.
DEFINE VARIABLE lastOrdNum as INTEGER NO-UNDO.
DEFINE VARIABLE jeNum AS CHARACTER NO-UNDO.
DEFINE VARIABLE pm AS CHARACTER NO-UNDO.
DEFINE VARIABLE pmEmail AS CHARACTER NO-UNDO.
DEFINE VARIABLE thisPackNum as INTEGER NO-UNDO.
DEFINE VARIABLE lastPackNum as INTEGER NO-UNDO.
DEFINE VARIABLE opLineRel AS CHARACTER NO-UNDO.
DEFINE VARIABLE ts AS CHARACTER NO-UNDO.
DEFINE VARIABLE td AS DATE INITIAL TODAY NO-UNDO.
DEFINE VARIABLE cc AS CHARACTER NO-UNDO.

tn = STRING(ShipHead.TrackingNumber).
thisPackNum = ShipHead.PackNum.
pmEmail = "ckrusen@XXXXXX.com".

ASSIGN Email-Mime-Header = "type=text/html:charset=us-ascii:filetype=ascii".

/************************************/
/* Create the new body of the email */
ASSIGN NewEmailBody = "<html><body><pre style='font: monospace'>".

NewEmailBody = NewEmailBody + "(This is an automated message. Please do not reply)" + chr(10) + chr(10).
NewEmailBody = NewEmailBody + "<b>FOR INTERNAL USE ONLY !!!</b>" + chr(10).

ordCount = 0.
lastOrdNum = -1.


/********************************************************************/
/* Get related Order info - J&E Num, Vista Num, PM, PM's email, ... */
FIND FIRST ShipDtl WHERE (ShipDtl.Company = ShipHead.Company) AND (ShipDtl.PackNum = ShipHead.PackNum) NO-LOCK NO-ERROR.
ordNum = ShipDtl.OrderNum.

FIND FIRST OrderHed WHERE (OrderHed.Company = 'MC') AND (OrderHed.OrderNum = ordNum) NO-LOCK NO-ERROR.
IF AVAILABLE OrderHed  Then DO:
  pm = OrderHed.ShortChar09.
  jeNum = OrderHed.ShortChar02.
END.

FIND FIRST UD05 WHERE (Ud05.Company = 'MC') AND (UD05.ShortChar01 = pm) NO-LOCK NO-ERROR.
IF AVAILABLE UD05 THEN pmEmail = UD05.ShortChar02.


ASSIGN Email-Subject = "Shipment Notification.  Order#: " + jeNum + " / " + STRING(OrderHed.OrderNum) + ", Packer#: " + STRING(ShipHead.PackNum).

/*****************************/
/* build order shipment info */

/* todays packers */
FIND Customer WHERE (Customer.Company = ShipHead.Company) AND (Customer.CustNum = ShipHead.CustNum) NO-LOCK.
FIND ShipDtl WHERE (ShipDtl.Company = ShipHead.Company) AND (ShipDtl.PackNum = ShipHead.PackNum) NO-LOCK NO-ERROR.
FIND ShipTo WHERE (ShipTo.Company = ShipHead.Company) AND (ShipTo.CustNum = ShipHead.CustNum) AND (ShipTo.ShipToNum = ShipHead.ShipToNum) NO-LOCK NO-ERROR.

NewEmailBody = NewEmailBody +       "************************ THIS SHIPMENT ************************ " + chr(10).
NewEmailBody = NewEmailBody + "Packer: " + STRING(ShipHead.PackNum) + ",  J&E Job#:" + jeNum + ",  Vista Order#:" + STRING(ordNum) + chr(10).
NewEmailBody = NewEmailBody + "Tracking #(s): " + foo(tn) + chr(10) + chr(10).
NewEmailBody = NewEmailBody + "Ship To:" + chr(10).
NewEmailBody = NewEmailBody + foo(ShipTo.Name) + " (" + STRING(Customer.CustId) + ")" + chr(10).
NewEmailBody = NewEmailBody + foo(ShipTo.Address1) + chr(10).
if length(ShipTo.Address2) > 1 then NewEmailBody = NewEmailBody + foo(ShipTo.Address2) + chr(10).
if length(ShipTo.Address3) > 1 then NewEmailBody = NewEmailBody + foo(ShipTo.Address3) + chr(10).
NewEmailBody = NewEmailBody + foo(ShipTo.City) + ", " + foo(ShipTo.State) + "  " +  foo(ShipTo.ZIP) + chr(10).
NewEmailBody = NewEmailBody + chr(10).

NewEmailBody = NewEmailBody + "Ord  Shp     Shp  Part                       Part" + chr(10).
NewEmailBody = NewEmailBody + "Line Qty     UOM  Number                     Description" + chr(10).
NewEmailBody = NewEmailBody + "==== ======= ===  =========================  =========================" + chr(10).

FOR EACH ShipDtl WHERE (ShipDtl.Company = ShipHead.Company) AND (ShipDtl.PackNum = ShipHead.PackNum):
  if( INDEX(ShipDtl.PartNum,"FREIGHT") = 0) then do:
    NewEmailBody = NewEmailBody + STRING(ShipDtl.OrderLine)  + FILL(" ",5 - LENGTH(STRING(ShipDtl.OrderLine))).
    NewEmailBody = NewEmailBody + STRING((ShipDtl.SellingInventoryShipQty + ShipDtl.SellingJobShipQty)).
    NewEmailBody = NewEmailBody + FILL(" ", 8 - LENGTH(STRING(ShipDtl.SellingInventoryShipQty + ShipDtl.SellingJobShipQty))).
    NewEmailBody = NewEmailBody + foo(ShipDtl.SalesUM + FILL(" ",5 - LENGTH(ShipDtl.SalesUM))).
    NewEmailBody = NewEmailBody + foo(SUBSTR(ShipDtl.PartNum,1,25) + FILL(" ",27 - LENGTH(ShipDtl.PartNum))).
    ts = substr(ShipDtl.LineDesc,1,25).
    IF(LENGTH(ts) >= 25) THEN ts = SUBSTR(ts,1,22) + "...".
    ts = foo(ts).
    NewEmailBody = NewEmailBody + ts.
    NewEmailBody = NewEmailBody + chr(10).
  END.
END.

/* end of finding orders for this shipment*/
NewEmailBody = NewEmailBody + chr(10) + chr(10).

/* find previous shipments for this order */
FOR First ShipDtl WHERE (ShipDtl.Company = ShipHead.Company  AND ShipDtl.OrderNum = ordNum AND ShipDtl.PackNum <> thisPackNum):
  NewEmailBody = NewEmailBody +       "************************ PREVIOUS SHIPMENTS ************************ " + chr(10).
end.

lastPackNum = 0.
FOR EACH ShipDtl WHERE (ShipDtl.Company = ShipHead.Company  AND ShipDtl.OrderNum = ordNum)  BY ShipDtl.PackNum DESCENDING:
  if(ShipDtl.PackNum <> thisPackNum) then do:
    if(ShipDtl.PackNum <> lastPackNum) then do:
      NewEmailBody = NewEmailBody + chr(10) + "Packer#: " + STRING(ShipDtl.PackNum) + chr(10).  
      NewEmailBody = NewEmailBody + "Ord  Shp     Shp  Part                       Part" + chr(10).
      NewEmailBody = NewEmailBody + "Line Qty     UOM  Number                     Description" + chr(10).
      NewEmailBody = NewEmailBody + "==== ======= ===  =========================  =========================" + chr(10).
      lastPacknum = ShipDtl.PackNum.
    end.
    NewEmailBody = NewEmailBody + STRING(ShipDtl.OrderLine)  + FILL(" ",5 - LENGTH(STRING(ShipDtl.OrderLine))).
    NewEmailBody = NewEmailBody + STRING((ShipDtl.SellingInventoryShipQty + ShipDtl.SellingJobShipQty)).
    NewEmailBody = NewEmailBody + FILL(" ", 8 - LENGTH(STRING(ShipDtl.SellingInventoryShipQty + ShipDtl.SellingJobShipQty))).
    NewEmailBody = NewEmailBody + foo(ShipDtl.SalesUM + FILL(" ",5 - LENGTH(ShipDtl.SalesUM))).
    NewEmailBody = NewEmailBody + foo(SUBSTR(ShipDtl.PartNum,1,25) + FILL(" ",27 - LENGTH(ShipDtl.PartNum))).

    ts = substr(ShipDtl.LineDesc,1,25).
    IF(LENGTH(ts) >= 25) THEN ts = SUBSTR(ts,1,22) + "...".
    ts = foo(ts).
    NewEmailBody = NewEmailBody + ts.
    NewEmailBody = NewEmailBody + chr(10).
  end.
end.




ASSIGN Email-Subject = "Shipment Notification.  Order#: " + jeNum + " / " + STRING(OrderHed.OrderNum) + ", Packer#: " + STRING(ShipHead.PackNum).

/* debugging stuff */
IF (pmEmail = "ckrusen@XXXXXX.com") then do:
  /********
  NewEmailBody = NewEmailBody + chr(10) + STRING(ASC(SUBSTR(tn,1,1))).
  NewEmailBody = NewEmailBody + chr(10) + STRING(ASC(SUBSTR(tn,2,1))).
  NewEmailBody = NewEmailBody + chr(10) + STRING(ASC(SUBSTR(tn,3,1))).
  NewEmailBody = NewEmailBody + chr(10) + STRING(ASC(SUBSTR(tn,4,1))).
  ************/
END.


ASSIGN Email-To = "<" + REPLACE(pmEmail,";",">;<") + ">".

/*cc = "<rjacobs@XXXXXX.com>; <jpacheco@XXXXXX.com>; <ejacob@XXXXXX.com>; <slaemmle@XXXXXX.com>; <lporter@XXXXXX.com>; <calvin.krusen@YYYYYYY.net>;".*/
/* get CC list from BAM */
cc = Email-CC.

/* remove PM from CC: */
cc = REPLACE(cc, Email-To, "; ").

/* overide the CC list when I'm the PM - This is for testing so others don't get the test messages */
IF (pmEmail = "ckrusen@XXXXXX.com") then cc = "<calvin.krusen@YYYYYY.net>".
ASSIGN Email-CC = cc.

/* add To and CC to body text.  This is just fro debugging*/
/***********
NewEmailBody = NewEmailBody + chr(10) + chr(10) + "To: " + pmEmail.
NewEmailBody = NewEmailBody + chr(10) + "CC: " + cc.
**************/

NewEmailBody = NewEmailBody + "</pre></body></html>".

/* set Email Body */
ASSIGN Email-Text = NewEmailBody.

  

This is saved as a .P file, and that filename is entered in the BAM setup.

There’s a lot of irrelevant stuff in there. You’ll need to focus on the lines that start with

ASSIGN Email-Mime-Header = ...
ASSIGN NewEmailBody = ...
ASSIGN Email-Subject = ...
ASSIGN Email-To = ...
ASSIGN Email-CC = ...
ASSIGN Email-Text = ...

Thank you Calvin; that’s some handy code especially as it generates an HTML based message.

I read through the code and didn’t see anything related to attaching a report printout. The major challenge for me right now is attaching a printed report to the email in Vantage 8. Do you have any insight on that? Thanks again!

I don’t think you can do it very easily.

That’s why my code had to practically build the Packing Slip in the body. Also because we added other info that’s not on the packer.

If APR (Advanced Print Routing) exists for V8, that might work for you. We use APR in E10, and it allows setting up the ability to email docs that you would normally print.

1 Like

Do you have APM / Doclink? We use Doclink to email our AR Invoices as an attachment and although I haven’t tried it I can’t see why you can’t schedule a report to send via that ‘printer’.

1 Like

Both great work-arounds, thank you! So doing this directly with a BPM is not possible but there may be ways to achieve this otherwise.

Ancient Progress coming up. I did this some time ago with a progress utility called smtpmail.p to send excel files out for quoting. I had help in those days from Geoff Crawford one of the contributors to the project on getting it to work.

I started in 904, so I don’t know 8, but assuming it is the same then the smtpmail.zip goes in a util directory under your main Vantage directory. Set your email server in vars-smtp.i and use testsm.p in any update to check the setup.

You should be able to make the file for the attachment in the BAM like @ckrusen’s and then set SendMail = false to stop Vantage from emailing and use smtpmail instead.

Greg

bpm send excel smtpmail.p (2.9 KB)smtpmail.zip (51.2 KB)

1 Like