One of the common requirements when we are implementing SAP Ariba Commerce Automation or Digital Supplier Network, is to send attachments inside the purchase order to Ariba Business Network, but this functionality is already included implementing the next Include in the User Exit EXIT_SAPLEINM_002:
INCLUDE ARBCIG_ORDER_REQUEST_002 IF FOUND.
But…what happens when you want to send the PDF of the purchase order, and this PDF is generated in a SAPScript form, that is executed inside the output type message:
This Output type is configured in NACE transaction where you enter the form name of the SAPScript that will be triggered:
The complication of this functionality is that this printout of the purchase order, is triggered when the output message is already processed and the purchase order is already approved, but when you are sending the purchase order to Ariba Business Network, this steps are not finished yet, so you must implement a logic to print the PDF of the purchase order, executing manually the SAPScript in real time when the PO is sent to Business Network.
We can do that implementing the BADI ARBCIG_BADI_ATTACHMENT_UTIL where we process the attachments of the PO.
We only need the method PRE_ATTACHMENT_PROCESS:
Inside this method, we will implement the next logic:
- Search in NAST table with the PO ID if exists the message you are configured in NACE transaction for the purchase order you are approving.
- Read the data of the PO from MF ME_READ_PO_FOR_PRINTING.
- Execute the MF ECP_PRINT_PO with the form ID.
- Read the OTF data of the form with MF READ_OTF_FROM_MEMORY.
- Convert OTF data to PDF with MF CONVERT_OTF.
- Encrypt the PDF from Hexadecimal to Base64 with MF SCMS_BASE64_ENCODE_STR.
- Complete the E1ARBCIG_ATTACH_HDR_DET segment with header data of attachment.
- Complete the E1ARBCIG_ATTACH_CONTENT_DET segment with the content of Base64 string.
All this steps are detailed in the next code:
method IF_ARBCIG_ATTACHMENT_UTIL~PRE_ATTACHMENT_PROCESS.
DATA: gint_nast TYPE nast,
lv_count TYPE i,
lv_ebeln TYPE ebeln,
ent_screen TYPE c,
ent_retco TYPE i,
l_nast TYPE nast,
l_druvo TYPE t166k-druvo,
l_from_memory,
toa_dara TYPE toa_dara,
arc_params TYPE arc_params,
aux_form TYPE tnapr-fonam VALUE 'ZMMSS_PEDCOMPRAS',
lv_message TYPE tnapr-fonam VALUE 'ZPC',
lt_docs TYPE TABLE OF docs,
l_doc TYPE meein_purchase_doc_print,
otf TYPE TABLE OF itcoo,
pdf_bytecount TYPE i,
nom_archivo TYPE string,
pdfout TYPE TABLE OF tline,
lv_debug TYPE char1,
pdf TYPE XSTRING,
ls_e1edk01 TYPE e1edk01,
ls_hdr_det TYPE E1ARBCIG_ATTACH_HDR_DET,
ls_hdr_content TYPE E1ARBCIG_ATTACH_CONTENT_DET,
idoc_data TYPE edidd,
lv_base64 TYPE string,
len TYPE i,
lv_offset_mx TYPE i,
lv_offset_mn TYPE i,
div TYPE i,
temp TYPE i.
*"---------------------------------------------------------------------
*" NOTES:
*" 1) Control display of PO in GUI window
*" ENT_SCREEN = 'X' => PO is displayed in GUI window
*" ENT_SCREEN = space => Spool file of the PO is created
*" Spool number is returned in message
*" 2) Write PO to memory as OTF
*" NAST-SORT1 = 'SWP' => PO is written to memory as OTF
*" Memory ID = PO Number - Use function
*" READ_OTF_FROM_MEMORY to retrieve
*" NAST-SORT1 = space => PO is NOT written to memory
*"---------------------------------------------------------------------
*Infinite LOOP only for debug
SELECT SINGLE low
FROM ARBCIG_TVARV
WHERE name = 'DEBUG_PRE_ATTACHMENT_PROCESS'
INTO @lv_debug.
IF lv_debug EQ 'X'.
WHILE lv_debug IS NOT INITIAL.
ENDWHILE.
ENDIF.
*First we obtain the PO ID from field
*Belnr from segment e1edk01
READ TABLE c_edidd[] INTO idoc_data INDEX 1.
CHECK idoc_data-segnam EQ 'E1EDK01'.
MOVE idoc_data-sdata TO ls_e1edk01.
lv_ebeln = ls_e1edk01-belnr.
IF lv_ebeln IS NOT INITIAL.
*Field lv_message is the output type message where the form is configured
SELECT SINGLE *
FROM nast INTO gint_nast WHERE objky EQ lv_ebeln
AND kschl EQ lv_message.
*We ensure the output type exists for the PO.
CHECK sy-subrc EQ 0.
gint_nast-sort1 = 'SWP'.
IF gint_nast-aende EQ space.
l_druvo = '1'.
ELSE.
l_druvo = '2'.
ENDIF.
CLEAR ent_retco.
CALL FUNCTION 'ME_READ_PO_FOR_PRINTING'
EXPORTING
IX_NAST = gint_nast
IX_SCREEN = ent_screen
IMPORTING
EX_RETCO = ent_retco
DOC = l_doc
EX_NAST = l_nast
CHANGING
CX_DRUVO = l_druvo
CX_FROM_MEMORY = l_from_memory.
* CHECK ent_retco EQ 0.
IF ent_retco EQ 3.
"It means the PO is not released yet, but this is normal, dont panic.
CLEAR ent_retco.
ENDIF.
CHECK ent_retco EQ 0.
*Field aux_form is the SAPScript ID form.
CALL FUNCTION 'ECP_PRINT_PO'
EXPORTING
IX_NAST = l_nast
IX_DRUVO = l_druvo
DOC = l_doc
IX_SCREEN = ent_screen
* IX_XFZ =
* IX_MFLAG = ' '
IX_FROM_MEMORY = l_from_memory
IX_TOA_DARA = toa_dara
IX_ARC_PARAMS = arc_params
IX_FONAM = aux_form
IMPORTING
EX_RETCO = ent_retco.
CLEAR otf.
CALL FUNCTION 'READ_OTF_FROM_MEMORY'
EXPORTING
MEMORY_KEY = l_nast-objky " PO Number
TABLES
OTF = otf
* EXCEPTIONS
* MEMORY_EMPTY = 1
* OTHERS = 2
.
IF sy-subrc <> 0.
* RAISE otf_error.
ENDIF.
*We transform OTF to PDF
CALL FUNCTION 'CONVERT_OTF'
EXPORTING
format = 'PDF'
IMPORTING
bin_filesize = pdf_bytecount
BIN_FILE = PDF
TABLES
otf = otf
lines = pdfout
EXCEPTIONS
err_max_linewidth = 1
err_format = 2
err_conv_not_possible = 3
OTHERS = 4.
IF sy-subrc <> 0.
* RAISE error. " oops
ENDIF.
*We transform the PDF from Hexa to Base64
CHECK PDF IS NOT INITIAL.
CALL FUNCTION 'SCMS_BASE64_ENCODE_STR'
EXPORTING
INPUT = PDF
IMPORTING
OUTPUT = lv_base64.
*If all its OK, we already have the PDF in Base64
CHECK lv_base64 IS NOT INITIAL.
CLEAR idoc_data.
*We insert segment E1ARBCIG_ATTACH_HDR_DET.
idoc_data-segnam = 'E1ARBCIG_ATTACH_HDR_DET'.
CONCATENATE lv_ebeln '.pdf' INTO ls_hdr_det-filename.
ls_hdr_det-charset = 'UTF-8'.
ls_hdr_det-contentid = '1'.
ls_hdr_det-contenttype = 'application/pdf'.
ls_hdr_det-contentlength = pdf_bytecount.
CONDENSE ls_hdr_det-contentlength NO-GAPS.
MOVE ls_hdr_det TO idoc_data-sdata.
APPEND idoc_data TO c_edidd[].
*We insert segments E1ARBCIG_ATTACH_CONTENT_DET.
CLEAR idoc_data.
idoc_data-segnam = 'E1ARBCIG_ATTACH_CONTENT_DET'.
len = strlen( lv_base64 ).
lv_offset_mx = 255.
lv_offset_mn = 0.
div = ceil( len / 255 ).
do div times.
clear ls_hdr_content.
IF lv_offset_mn GE len.
"Last loop
EXIT.
ELSE.
temp = len - lv_offset_mn.
IF temp LT lv_offset_mx.
"Last loop
ls_hdr_content-content = lv_base64+lv_offset_mn(temp).
MOVE ls_hdr_content TO idoc_data-sdata.
APPEND idoc_data TO c_edidd[].
EXIT.
ENDIF.
ls_hdr_content-content = lv_base64+lv_offset_mn(lv_offset_mx).
MOVE ls_hdr_content TO idoc_data-sdata.
APPEND idoc_data TO c_edidd[].
lv_offset_mn = lv_offset_mn + lv_offset_mx.
ENDIF.
enddo.
ENDIF.
endmethod.
Summary
As a final result, the buyer will only add the message output type in the purchase order, without need of attaching anything to the purchase order, and the system automatically will print this PDF in background and will be attached this PDF to the IDOC sent to business network.
And finally, the supplier will have the PDF inside the purchase order in business network: