z2soo's Blog

오더의 첨부파일을 메일로 발송 본문

SAP/ABAP

오더의 첨부파일을 메일로 발송

z2soo 2022. 12. 26. 09:25
반응형

1. 오더에 파일 첨부 (Attachment)

구매요청, 오더, 자재문서 등 오더(문서)에 파일을 추가하는 경우가 있다. txt, xlsx, pdf, img 등 다양한 형태의 파일이 첨부 가능하다. 자재문서를 예시로 보면 좌측 상단의 Object Service > 생성 > 첨부파일 생성 을 통해 첨부 파일을 추가할 수 있다. 

 

 

첨부된 파일은 아래와 같이 확인 가능하다. 

 

 

2. 오더의 첨부파일을 메일로 발송

오더를 조회하는 레포트 프로그램 중 해당 오더의 attachment 를 다운받거나 메일로 바로 전송하는 기능을 추가하기도 한다. 아래 로직은 오더의 attachment를 조회하여 입력되는 메일 수신자에게 바로 전송하는 function 에 대한 내용이다. 참고로 SAP에서는 이전에 사용하던  메일 발송 펑션보다는  클래스 ( cl_bcs )를 사용하는 것을 권장한다. 

  • SO_DOCUMENT_SEND_API1 : 하나의 첨부파일 추가만 가능
  • SO_NEW_DOCUMENT_ATT_SEND_API1 : 발신자 지정 불가
 # Import/Export/Tables 항목
	#I_SUBJECT	TYPE	CHAR200         #메일제목
	#I_SENDER	TYPE	SALRTDRCPT      #메일발송자
	#I_OBJKEY	TYPE	SWO_TYPEID      #오브젝트키 
	#I_CLSNAM	TYPE	BDS_CLSNAM      #오브젝트의 클래스 이름
	#E_STATUS	TYPE	BAPI_MTYPE      #결과(성공, 실패)
	#E_MESSAGE	TYPE	BAPI_MSG        #결과(메시지)
	#LT_MAIL_TEXT	LIKE	SOLI        #메일본문
	#LT_RECEIVER	LIKE	SOMLRECI1   #메일수신자
 
 # 펑션 내부 로직
 CONSTANTS:
    lv_c_error   TYPE c VALUE 'E',
    lv_c_success TYPE c VALUE 'S'.

  DATA:
    lc_send_request   TYPE REF TO cl_bcs,            #클래스
    lcl_document      TYPE REF TO cl_document_bcs,   #메일(문서)
    lcx_exception     TYPE REF TO cx_bcs,            #예외 항목
    lcl_sender        TYPE REF TO cl_sapuser_bcs,
    lif_recipient     TYPE REF TO if_recipient_bcs,
    lt_text           TYPE bcsy_text,                #본문 내역 텍스트 전체
    lt_binary_content TYPE solix_tab,                #첨부파일 항목
    ls_receiver       TYPE somlreci1,                #메일 수신인
    lv_len            TYPE so_obj_len,               #메일 본문 길이
    lv_subject        TYPE so_obj_des,               #메일 제목
    lv_sent_to_all    TYPE os_boolean.               #모든 수신인 전송

  TRY.
      #1. 요청 오브젝트 생성
      lc_send_request = cl_bcs=>create_persistent( ).

      #2. 메일 제목 
      CLEAR lv_subject.
      lv_subject = i_subject. 	#func import 값

      #3. 메일 내용 
      DATA: ls_text LIKE LINE OF lt_text.
      CLEAR: lt_text, ls_receiver.

      IF lt_mail_text IS NOT INITIAL.
        LOOP AT lt_mail_text INTO DATA(ls_mail_text).
          APPEND ls_mail_text-line TO lt_text.         
        ENDLOOP.
      ENDIF.

      #4.메일 길이
      CLEAR  lv_len.
      DESCRIBE TABLE lt_text LINES lv_len.

      #5.메일 생성
      lcl_document = cl_document_bcs=>create_document(
        i_type    = 'RAW'
        i_text    = lt_text
        i_length  = lv_len
        i_subject = lv_subject ).

      #6. Business object 첨부파일 link 정보 읽어오기
      DATA:
        ls_object      TYPE sibflporb,
        lt_rel_options TYPE obl_t_relt,
        lt_links       TYPE obl_t_link,
        ls_links       TYPE obl_s_link.

      CLEAR: ls_object, lt_rel_options, lt_links, ls_links.
      ls_object = VALUE #( instid =  i_objkey
                           typeid = i_clsnam
                           catid = 'BO' ).

      lt_rel_options = VALUE #( ( low = 'ATTA'
                                  sign = 'I'
                                  option = 'EQ' ) ).

      TRY.
          CALL METHOD cl_binary_relation=>read_links_of_binrels
            EXPORTING
              is_object           = ls_object
              it_relation_options = lt_rel_options
              ip_role             = 'GOSAPPLOBJ'
            IMPORTING
              et_links            = lt_links.

        CATCH cx_obl_parameter_error. # Incorrect Calling of Interface
        CATCH cx_obl_internal_error.  # Internal Error of Relationship Service
        CATCH cx_obl_model_error.     # Error with Model Roles
      ENDTRY.

      IF sy-subrc <> 0.
        #FKK_CM	040	첨부파일을 읽는 동안 오류가 발생했습니다.
        MESSAGE e040(fkk_cm) INTO e_message.
        e_status = lv_c_error.
        RETURN.
      ENDIF.

      IF lt_links IS INITIAL.
        #CRM_BUPA_ODATA  028 첨부파일이 없습니다.
        MESSAGE e028(crm_bupa_odata) INTO e_message.
        e_status = lv_c_error.
        RETURN.
      ENDIF.

      #첨부파일 정보로 파일 생성 및 메일에 첨부
      DATA :
        lv_doc_id     TYPE sofolenti1-doc_id,
        lt_cont_bin   TYPE TABLE OF solisti1,
        lt_cont_solix TYPE TABLE OF solix,
        ls_doc_data   TYPE sofolenti1,
        lv_lines      TYPE char12,
        lt_obj_header TYPE TABLE OF solisti1.

      LOOP AT lt_links  INTO ls_links.

        CLEAR: lv_doc_id, ls_doc_data, lt_cont_bin, lt_cont_solix, lt_binary_content.
        lv_doc_id = ls_links-instid_b.

        APPEND '&SO_FORMAT=BIN' TO lt_obj_header.

        #7. 첨부파일 content 읽어오기
        CALL FUNCTION 'SO_DOCUMENT_READ_API1'
          EXPORTING
            document_id                = lv_doc_id
          IMPORTING
            document_data              = ls_doc_data
          TABLES
            object_header              = lt_obj_header
            object_content             = lt_cont_bin
            contents_hex               = lt_cont_solix
          EXCEPTIONS
            document_id_not_exist      = 1
            operation_no_authorization = 2
            x_error                    = 3
            OTHERS                     = 4.

        IF sy-subrc <> 0.
          //FKK_CM	040	첨부파일을 읽는 동안 오류가 발생했습니다.
          MESSAGE e040(fkk_cm) INTO e_message.
          e_status = lv_c_error.
          RETURN.
        ENDIF.
        
        #8. Binary 변환
        IF  lt_cont_solix  IS INITIAL AND lt_cont_bin IS NOT INITIAL.
         #TXT 파일은 아래 펑션 사용시 encoding 문제로 한글이 깨짐
         #다른 파일 형태는 아래 펑션 사용 가능
#          CALL FUNCTION 'SO_SOLITAB_TO_SOLIXTAB'
#            EXPORTING
#              ip_solitab  = lt_cont_bin
#            IMPORTING
#              ep_solixtab = lt_binary_content.
          TRY.
            #TXT 파일 때문에 아래 펑션으로 변경
              CALL METHOD cl_bcs_convert=>txt_to_solix
                EXPORTING
                  it_soli     = lt_cont_bin
                  iv_codepage = '8500' #Encoding
                IMPORTING
                  et_solix    = lt_binary_content.
            CATCH cx_bcs.
          ENDTRY.

          #텍스트의 경우 doc size가 정확하지 않아 다시 계산
          IF ls_doc_data-obj_type = 'TXT'.
            lv_lines = lines( lt_cont_bin ) * 255.
            SHIFT lv_lines LEFT DELETING LEADING ' ' .
            ls_doc_data-doc_size = lv_lines.
          ENDIF.

        ELSE.
          lt_binary_content = lt_cont_solix.

          #텍스트의 경우 doc size가 정확하지 않아 다시 계산
          IF ls_doc_data-obj_type = 'TXT'.
            lv_lines = lines( lt_cont_solix ) * 255.
            SHIFT lv_lines LEFT DELETING LEADING ' ' .
            ls_doc_data-doc_size = lv_lines.
          ENDIF.
        ENDIF.

        #9. 메일에 첨부파일 추가
        #빈 첨부파일인 경우도 있을 수 있으니 lt_cont_solix, lt_cont_bin 값이 initial이여도 첨부
        CALL METHOD lcl_document->add_attachment
          EXPORTING
            i_attachment_type     = ls_doc_data-obj_type
            i_attachment_language = ls_doc_data-obj_langu
            i_attachment_size     = ls_doc_data-doc_size
            i_attachment_subject  = ls_doc_data-obj_descr
            i_att_content_hex     = lt_binary_content.

        IF sy-subrc <> 0.
          #/PM0/ABP_CORR  100 첨부파일을 로드하는 중 오류가 발생했습니다.
          MESSAGE e100(/pm0/abp_corr) INTO e_message.
          e_status = lv_c_error.
          RETURN.
        ENDIF.
      ENDLOOP.

      #10. 메일 수신 발신 설정
      #메일을 요청에 추가
      CALL METHOD lc_send_request->set_document( lcl_document ).

      #발신자(아이디) 설정
      lcl_sender = cl_sapuser_bcs=>create( sy-uname ).
      CALL METHOD lc_send_request->set_sender
        EXPORTING
          i_sender = lcl_sender.

      #수신자 설정
      DATA: lv_smtp_addr TYPE ad_smtpadr.
      CLEAR: lv_smtp_addr, ls_receiver.

      LOOP AT lt_receiver INTO ls_receiver.
        CLEAR lv_smtp_addr.
        lv_smtp_addr = ls_receiver-receiver.
        lif_recipient = cl_cam_address_bcs=>create_internet_address( lv_smtp_addr ).
      ENDLOOP.

      CALL METHOD lc_send_request->add_recipient
        EXPORTING
          i_recipient = lif_recipient
          i_express   = 'X'.

      #11. 메일 발송
      CALL METHOD lc_send_request->send(
        EXPORTING
          i_with_error_screen = 'X'
        RECEIVING
          result              = lv_sent_to_all ).

    CATCH cx_bcs INTO lcx_exception.
      #예외처리
  ENDTRY.

  IF sy-subrc = 0.
    COMMIT WORK.
    #/CPD/CL_MSG  201 전자메일을 보냈습니다.
    MESSAGE s201(/cpd/cl_msg) INTO e_message.
    e_status = lv_c_success.
  ELSE.
    #/DMBE/CORE_BO  022 전자메일이 발송되지 않았습니다.
    MESSAGE s022(/dmbe/core_bo) INTO e_message.
    e_status = lv_c_error.
  ENDIF.

 

3. 메일 발송 확인

메일이 정상적으로 발송 되었는지 또는 어떤 형태로 발송되었는지 확인하는 방법은 아래 글을 참고하자. 

 

SAP Connect 메일 발송 확인

Key point SAP Connect T-Code : SOST SAP Connect SAP GUI에서 메일을 발송하고 메일이 잘 발송되었는지 확인 가능한 transaction 이다. 아래 화면을 보면 현재 발송을 한 항목이 없지만, 발송 요청 또는 완료시 리

z2soo.tistory.com

반응형
Comments