The complexity of the remittance advice set-up lies in the trigger program; whether to build a custom program or clone one of the delivered SAP payment advice programs.
In this example, we are cloning the SAP program RFFOAVIS_FPAYM
Create Z_ RFFOAVIS_FPAYM by copying RFFOAVIS_FPAYM.
Add selections for Floe e-mail type and flag to send immediately.
1: 2: 3: 4: 5: |
*/ FLOE modification /* SELECTION-SCREEN BEGIN OF BLOCK floe WITH FRAME TITLE text-002. PARAMETERS: p_etype TYPE /floe/etype_code MATCHCODE OBJECT /floe/etype, p_immed AS CHECKBOX. SELECTION-SCREEN END OF BLOCK floe. |
Create supporting text elements, and then create a copy of the INCLUDE program RFFORI06. Replace the include statement:
1: 2: 3: 4: 5: |
*/ FLOE modification /* */ Use copied INCLUDE for payment advice creation * INCLUDE rffori06. INCLUDE z_rffori06. *////////////////////* |
Save and activate Z_ RFFOAVIS_FPAYM.
Add the additional code to the new INCLUDE Z_RFFORI06 within the FORM AVIS, at the event AT END OF reguh-vblnr. This is when outputs are generated. Floe can be called immediately before the current trigger for output – in this example, before the call for printed payment advices:
* Ausgabe auf Fax oder Drucker (nur falls notwendig)
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: |
*/ FLOE modification /* DATA: l_addr1_complete TYPE szadr_addr1_complete, l_addr1_line TYPE szadr_addr1_line, l_adsmtp_line TYPE szadr_adsmtp_line, l_recipient_email TYPE ad_smtpadr, l_langu TYPE /floe/elang, l_subrc TYPE sysubrc. IF p_etype IS NOT INITIAL AND flg_kein_druck EQ 0. * Get recipient e-mail address. CALL FUNCTION 'ADDR_GET_COMPLETE' EXPORTING addrnumber = reguh-zadnr IMPORTING addr1_complete = l_addr1_complete EXCEPTIONS OTHERS = 4. IF sy-subrc EQ 0. * Check that internet address is available READ TABLE l_addr1_complete-adsmtp_tab INTO l_adsmtp_line INDEX 1. IF sy-subrc EQ 0. * Address found. l_recipient_email = l_adsmtp_line-adsmtp-smtp_addr. * Read communication language READ TABLE l_addr1_complete-addr1_tab INTO l_addr1_line INDEX 1. IF sy-subrc EQ 0. l_langu = l_addr1_line-data-langu. ENDIF. * Fill item table parameter REFRESH: l_t_regup. l_t_regup[] = tab_regup[]. CALL FUNCTION 'Z_FLOE_PAYMENT_ADVICE' EXPORTING im_etype = p_etype im_langu = l_langu im_immed = p_immed im_reguh = reguh im_regup = l_t_regup im_recipient = l_recipient_email IMPORTING ex_subrc = l_subrc. IF l_subrc EQ 0. * Success : stop advice from being printed. flg_kein_druck = 1. CLEAR tab_ausgabe. tab_ausgabe-name = 'FLOE payment advice sent by e-mail.'. tab_ausgabe-count = 1. COLLECT tab_ausgabe. ENDIF. ENDIF. ENDIF. ENDIF. *////////////////////* |
Here the call to Floe is made in a custom function Z_FLOE_PAYMENT_ADVICE
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: |
FUNCTION z_floe_payment_advice. *"---------------------------------------------------------------------- *"*"Local Interface: *" IMPORTING *" VALUE(IM_ETYPE) TYPE /FLOE/ETYPE_CODE *" VALUE(IM_LANGU) TYPE /FLOE/ELANG *" VALUE(IM_IMMED) TYPE FLAG *" VALUE(IM_REGUH) TYPE REGUH *" VALUE(IM_REGUP) TYPE FI_T_REGUP *" VALUE(IM_RECIPIENT) TYPE AD_SMTPADR *" EXPORTING *" VALUE(EX_SUBRC) TYPE SYSUBRC *"---------------------------------------------------------------------- DATA: ls_rec TYPE /floe/rec_email_s, lt_rec TYPE /floe/rec_email_t, ls_vars TYPE /floe/vars_s, lt_vars_temp TYPE /floe/vars_t, lt_vars TYPE /floe/vars_t, l_langu TYPE /floe/elang. * Fill recipient table * ls_rec-email = im_recipient. ls_rec-type = 1. APPEND ls_rec TO lt_rec. * * Fill variables table * * Header CALL METHOD /floe/core=>get_data_from_structure EXPORTING im_structure = im_reguh IMPORTING ex_vars = lt_vars_temp. * APPEND LINES OF lt_vars_temp TO lt_vars. * * Items CALL METHOD /floe/core=>get_data_from_table EXPORTING im_table = im_regup IMPORTING ex_vars = lt_vars_temp. * APPEND LINES OF lt_vars_temp TO lt_vars. * * Trigger Floe * CALL FUNCTION '/FLOE/EMAIL_OUT' EXPORTING im_etype = im_etype im_elang = im_langu * IM_ESUBJECT_LONG = im_rec_emails = lt_rec im_variables = lt_vars im_send_immediately = im_immed IMPORTING ex_subrc = ex_subrc. * ENDFUNCTION. |
The variables are filled from structure REGUH and table REGUP by creating variables for every field, using the sample methods /floe/core=>get_data_from_structure and /floe/core=>get_data_from_table. In fact an improvement would be to clone these methods, and change them so that the table name is added to the variable ID, such that we would have variables REGUH-WAERS and REGUP-WAERS, instead of different instances of variable WAERS.
Note that WAERS from REGUH has index ‘000’ and WAERS from REGUP has index 001, 002 etc. In this way you can identify the different variables in the Floe data user-exit.
Alternatively since only a subset of the data in REGUH and REGUP is required, you could write a function to fill Floe variables for the particular data you need instead of taking the entire structure/table.
All further data manipulation is handled within the Floe data user-exit.
One possible approach is to loop around the variable table (which will have many thousands of rows) in order to remove all the unwanted data.
The tasks in the user-exit include:
- Build address block (if required)
- Format SAP date fields
- Determine currency symbols
- Handle debit/credit indicators
- Determine any dynamic texts
- Format SAP money fields
This is a fairly typical list of the tasks required in the Floe data user-exit for SAP document output.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: |
METHOD email_data. *---------------------------------------------------------------------------* * EMAIL DATA USER-EXIT * *---------------------------------------------------------------------------* * This user-exit allows the manipulation of data which will be used to * * substitute the relevant placeholders inside the email body * *---------------------------------------------------------------------------* * Data is available in this userexit as follows: * * im_etype Email Type * im_elang Communication language used in the email - this will * determine the content of the html blocks * im_document External Document Reference * ch_variables Table of variables to be manipulated - fields * include the variable name, value, row number and * parent row number in the case of nested repeating * variable *---------------------------------------------------------------------------* * <<< Start of Customer Code >>> * *---------------------------------------------------------------------------* DATA: ls_vars TYPE /floe/vars_s. * Build Address block * DATA: l_address TYPE string, ls_t005t TYPE t005t. * CLEAR ls_vars. READ TABLE ch_variables WITH KEY var_code = 'ZNME3' INTO ls_vars. IF ls_vars-value NE space. CONCATENATE ls_vars-value '<br/>' INTO l_address. ENDIF. CLEAR ls_vars. READ TABLE ch_variables WITH KEY var_code = 'ZNME4' INTO ls_vars. IF ls_vars-value NE space. CONCATENATE l_address ls_vars-value '<br/>' INTO l_address. ENDIF. CLEAR ls_vars. READ TABLE ch_variables WITH KEY var_code = 'ZPFAC' INTO ls_vars. IF ls_vars-value NE space. CONCATENATE l_address ls_vars-value '<br/>' INTO l_address. ENDIF. CLEAR ls_vars. READ TABLE ch_variables WITH KEY var_code = 'ZSTRA' INTO ls_vars. IF ls_vars-value NE space. CONCATENATE l_address ls_vars-value '<br/>' INTO l_address. ENDIF. CLEAR ls_vars. READ TABLE ch_variables WITH KEY var_code = 'ZORT1' INTO ls_vars. IF ls_vars-value NE space. CONCATENATE l_address ls_vars-value '<br/>' INTO l_address. ENDIF. CLEAR ls_vars. READ TABLE ch_variables WITH KEY var_code = 'ZPST1' INTO ls_vars. IF ls_vars-value NE space. CONCATENATE l_address ls_vars-value '<br/>' INTO l_address. ENDIF. CLEAR ls_vars. READ TABLE ch_variables WITH KEY var_code = 'ZLAND' INTO ls_vars. IF ls_vars-value NE space. SELECT SINGLE * FROM t005t INTO ls_t005t WHERE spras = im_elang AND land1 = ls_vars-value+0(2). ls_vars-value = ls_t005t-landx. CONCATENATE l_address ls_vars-value '<br/>' INTO l_address. ENDIF. * CLEAR ls_vars. ls_vars-var_code = 'ADDRESS'. ls_vars-value = l_address. APPEND ls_vars TO ch_variables. * * Convert document date DATA: l_olddate TYPE datum, l_newdate TYPE string. CLEAR ls_vars. READ TABLE ch_variables WITH KEY var_code = 'ZALDT' INTO ls_vars. IF sy-subrc EQ 0. * l_olddate = ls_vars-value. * CALL FUNCTION 'CONV_EXIT_LDATE_OUTPUT_LANGU' EXPORTING input = ls_vars-value language = im_elang IMPORTING output = l_newdate. * REPLACE ALL OCCURRENCES OF '.' IN l_newdate WITH ''. * ls_vars-value = l_newdate. MODIFY ch_variables INDEX sy-tabix FROM ls_vars. * ENDIF. * Format dates LOOP AT ch_variables INTO ls_vars WHERE var_code EQ 'BLDAT'. * l_olddate = ls_vars-value. * CALL FUNCTION 'CONVERT_DATE_TO_EXTERNAL' EXPORTING date_internal = l_olddate IMPORTING date_external = l_newdate. * ls_vars-value = l_newdate. MODIFY ch_variables INDEX sy-tabix FROM ls_vars. * ENDLOOP. * * Determine currency symbol * DATA: l_curry TYPE string. READ TABLE ch_variables WITH KEY var_code = 'WAERS' INTO ls_vars. CASE ls_vars-value. WHEN 'GBP'. l_curry = '£'. WHEN 'USD'. l_curry = '$'. WHEN 'EUR'. l_curry = '€'. WHEN OTHERS. l_curry = ls_vars-value. ENDCASE. * ls_vars-var_code = 'CURRY'. ls_vars-value = l_curry. APPEND ls_vars TO ch_variables. * * Debit/credit indicator * LOOP AT ch_variables INTO ls_vars WHERE var_code EQ 'SHKZG'. IF ls_vars-value = 'S'. ls_vars-value = '-'. ELSE. CLEAR ls_vars-value. ENDIF. MODIFY ch_variables FROM ls_vars INDEX sy-tabix. ENDLOOP. * * Logic to show/hide text * DATA l_value TYPE p DECIMALS 2. READ TABLE ch_variables WITH KEY var_code = 'RBETR' INTO ls_vars. l_value = ls_vars-value. IF l_value EQ 0. CLEAR ls_vars. ls_vars-var_code = 'SH_ZERO'. CLEAR ls_vars-value. APPEND ls_vars TO ch_variables. ls_vars-var_code = 'SH_NONZERO'. ls_vars-value = 'display:none;'. APPEND ls_vars TO ch_variables. ELSE. CLEAR ls_vars. ls_vars-var_code = 'SH_NONZERO'. CLEAR ls_vars-value. APPEND ls_vars TO ch_variables. ls_vars-var_code = 'SH_ZERO'. ls_vars-value = 'display:none;'. APPEND ls_vars TO ch_variables. ENDIF. * * Format quantities * DATA: l_qty TYPE p DECIMALS 2, l_qty_char type char16. set country 'GB'. "Arch System only LOOP AT ch_variables INTO ls_vars WHERE var_code EQ 'RBETR' OR var_code EQ 'WRBTR'. * l_qty = ls_vars-value. write l_qty to l_qty_char currency 'GBP'. "Use currency variable instead for multi-country solution ls_vars-value = l_qty_char. MODIFY ch_variables FROM ls_vars INDEX sy-tabix. * ENDLOOP. * *---------------------------------------------------------------------------* * <<< End of Customer Code >>> * *---------------------------------------------------------------------------* ENDMETHOD. |
The e-mail template is made of various sections:
WRAPPER:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <title>Arch Payment Advice</title> <style type="text/css">a.archLink{ font-family:Segoe UI; color:#4F81BD; } @media only screen and (max-width:480px){ /* Force iOS Mail to render the email at full width. */ body{ width:100% !important; min-width:100% !important; } /* Set width of maintable */ .maintable{ clear: both; width:95% !important; } }</style> </head> <body> <center> <table align="center" border="0" cellpadding="0" cellspacing="0" height="100%" width="600" id="maintable"> <tr> <td align="center" valign="top"> #ARCH_PA_HEADER# #ARCH_PA_BODY# #ARCH_PA_FOOTER# </td> </tr> </table> </center> </body> </html> |
HEADER:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: |
<table border="0" cellspacing="0" cellpadding="2" width="100%" id="header_section"> <tr> <td bgcolor="#A5CA3F" height="70"> <img src="http://www.arch-global.com/wp-content/themes/arch_3.0/_layout/images/logo.jpg" alt="Arch Logo" width="70" height="70"/></td> <td valign="bottom" bgcolor="#A5CA3F" align="right" style="font-family: Arial, Helvetica; font-size:20px; color:#FFFFFF; line-height:140%;"><strong>Payment Advice</strong></td> <td bgcolor="#A5CA3F" width="5px"> </td> </tr> <tr> <td colspan="3"> </td> </tr> </table> |
BODY:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: |
<table align="center" border="0" cellspacing="0" cellpadding="2" width="100%" id="body_section"> <tr> <td width="15%" style="font-family: Segoe UI, Arial, Helvetica; font-size:14px;"><strong>Date:</strong></td> <td style="font-family: Segoe UI, Arial, Helvetica; font-size:14px;">&CURRENT_DATE&</td> </tr> <tr> <td style="font-family: Segoe UI, Arial, Helvetica; font-size:14px;"><strong>Supplier:</strong></td> <td style="font-family: Segoe UI, Arial, Helvetica; font-size:14px;">&ZNME1& &ZNME2&</td> </tr> <tr> <td> </td> <td style="font-family: Segoe UI, Arial, Helvetica; font-size:14px;">&ADDRESS&</td> </tr> <tr> <td colspan="2" style="border-bottom:3px solid #A5CA3F;"> <p> </p> <p style="font-family: Segoe UI, Arial, Helvetica; font-size:14px; &SH_NONZERO&">Please note that the following payments have been processed with document &VBLNR& on &ZALDT&.</p> <p style="font-family: Segoe UI, Arial, Helvetica; font-size:14px; &SH_ZERO&">Please note that the following due items have been cleared to give a zero balance.</p> <p style="font-family: Segoe UI, Arial, Helvetica; font-size:14px;">If you have any queries about this notification please contact us on +44 (0) 208 987 0440.</p> <p style="font-family: Segoe UI, Arial, Helvetica; font-size:14px;">Kind regards,</p> <p style="font-family: Segoe UI, Arial, Helvetica; font-size:14px;"><strong>Arch Customer Services</strong></p> <p> </p> </td> </tr> <tr> <td colspan="2"> <table align="center" border="0" cellspacing="0" cellpadding="4" width="100%" id="items"> <tr> <td style="font-family: Segoe UI, Arial, Helvetica; font-size:14px; border-bottom:3px solid #A5CA3F;"><strong>Document </strong></td> <td style="font-family: Segoe UI, Arial, Helvetica; font-size:14px; border-bottom:3px solid #A5CA3F;"><strong>Your document </strong></td> <td style="font-family: Segoe UI, Arial, Helvetica; font-size:14px; border-bottom:3px solid #A5CA3F;"><strong>Date </strong></td> <td colspan="2" style="font-family: Segoe UI, Arial, Helvetica; font-size:14px; border-bottom:3px solid #A5CA3F;" align="right"> <strong>Deductions</strong></td> <td colspan="2" style="font-family: Segoe UI, Arial, Helvetica; font-size:14px; border-bottom:3px solid #A5CA3F;" align="right"> <strong>Gross amount</strong></td> </tr> #ARCH_PA_ITEMS# <tr> <td colspan="5" style="font-family: Segoe UI, Arial, Helvetica; font-size:14px; border-top:3px solid #A5CA3F;"><strong> Total</strong></td> <td style="font-family: Segoe UI, Arial, Helvetica; font-size:14px; border-top:3px solid #A5CA3F;" align="right"> <strong>&CURRY&</strong></td> <td style="font-family: Segoe UI, Arial, Helvetica; font-size:14px; border-top:3px solid #A5CA3F;" align="right"> <strong>&RBETR&</strong></td> </tr> </table> </td> </tr> <tr> <td> <p align="justify" style="font-family: Segoe UI, Arial, Helvetica; font-size:14px; line-height:140%;"> </p> </td> </tr> </table> |
ITEMS:
1: 2: 3: 4: 5: 6: 7: 8: 9: |
<tr> <td style="font-family: Segoe UI, Arial, Helvetica; font-size:14px;">&BELNR&</td> <td style="font-family: Segoe UI, Arial, Helvetica; font-size:14px;">&XBLNR&</td> <td style="font-family: Segoe UI, Arial, Helvetica; font-size:14px;">&BLDAT&</td> <td align="right" style="font-family: Segoe UI, Arial, Helvetica; font-size:14px;">&CURRY&</td> <td align="right" style="font-family: Segoe UI, Arial, Helvetica; font-size:14px;">&SKNTO&</td> <td align="right" style="font-family: Segoe UI, Arial, Helvetica; font-size:14px;">&CURRY&</td> <td align="right" style="font-family: Segoe UI, Arial, Helvetica; font-size:14px;">&SHKZG&&WRBTR&</td> </tr> |
FOOTER:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: |
<table align="center" border="0" cellspacing="0" cellpadding="2" width="100%" id="footer_section"> <tr> <td colspan="4"> <p style="font-family: Segoe UI, Arial, Helvetica; color: #666666; font-size: 10px;"> Arch is the maker of the Adaptive Document Platform, providing:<br/><a class="archLink" style="font-family: Segoe UI, Arial, Helvetica; font-size: 10px;" href="http://www.arch-global.com/products/stelo">Stelo</a> for better Fiori apps,<br/> <a class="archLink" style="font-family: Segoe UI, Arial, Helvetica; font-size: 10px;" href="http://www.arch-global.com/products/floe">Floe </a> for SAP emails,<br/><a class="archLink" style="font-family: Segoe UI, Arial, Helvetica; font-size: 10px;" href="http://www.arch-global.com/products/varo">Varo</a> for SAP e-forms, and<br/> <a class="archLink" style="font-family: Segoe UI, Arial, Helvetica; font-size: 10px;" href="http://www.arch-global.com/products/aquiller">Aquiller</a> for SAP correspondence.</p> <p style="font-family: Segoe UI, Arial, Helvetica; color: #666666; font-size: 10px;">The content of this email is subject to our <a style="color: #666666;" href="http://www.arch-global.com/disclaimer">disclaimer</a>. Arch is registered in England & Wales, company #326 1503. Reg. office: The Mews, Elliott Road, London, W4 1PF, UK.</p> <p style="font-family: Segoe UI, Arial, Helvetica; color: #666666; font-size: 4px;"> </p> </td> </tr> <tr> <td height="35" align="center" valign="middle" style="border-bottom:2px solid #A5CA3F; border-top:2px solid #A5CA3F;"> <a href="http://twitter.com/archpulse"> <img src="http://arch-global.com/wp-content/uploads/2014/06/twitter_icon.jpg" border="0" alt="Twitter" width="24" height="24"/></a> </td> <td height="35" align="center" valign="middle" style="border-bottom:2px solid #A5CA3F; border-top:2px solid #A5CA3F;"> <a href="http://www.facebook.com/#!/pages/Arch/249564711794285"> <img src="http://www.arch-global.com/wp-content/uploads/2014/06/facebook_icon.jpg" border="0" alt="Facebook" width="24" height="24"/></a> </td> <td height="35" align="center" valign="middle" style="border-bottom:2px solid #A5CA3F; border-top:2px solid #A5CA3F;"> <a href="http://www.linkedin.com/company/arch-uk"> <img src="http://arch-global.com/wp-content/uploads/2014/06/linkedin_icon.jpg" border="0" alt="LinkedIn" width="24" height="24"/></a> </td> <td height="35" align="center" valign="middle" style="border-bottom:2px solid #A5CA3F; border-top:2px solid #A5CA3F;"> <a href="http://www.youtube.com/user/ArchFLM/"> <img src="http://arch-global.com/wp-content/uploads/2014/06/youtube_icon.jpg" border="0" alt="Twitter" width="24" height="24"/></a></td> </tr> </table> |
SeeYouTube video to see the results