ABAP Blog Posts
cancel
Showing results for 
Search instead for 
Did you mean: 

My requirement was to add an attachment to Freight Order in the "Attachments" section & Also, Send Tracking Email Notification to Customer with Tracking URL & Shipment details.
This was achieved using a Custom PPF Action maintained in Transaction SPPFCADM.

Irfan_Md_0-1783513783894.png

For this requirement I created an Adobe form in SFP.
Printed it in runtime and then added it to the Freight Order using the ROOT key in Schedule

Custom PPF Configuration Steps:

1. Run Transaction: SPPFCADM.

Irfan07_0-1781851424400.png

2. Define Action Profile and Actions

Irfan07_1-1781851542543.png

3. Custom Action.

Irfan07_2-1781851608159.png

Irfan07_5-1781851922341.png

4. Set Processing Types.

Irfan07_3-1781851667735.png

5. Condition of Configuration.

Irfan07_4-1781851723288.png

6. Technical Names->Schedule Condition.

Irfan07_6-1781852081656.png

7. Schedule Condition.

Irfan07_7-1781852143869.png

8. Schedule Condition Value: Z_US_TM_SCH_PPF_HAZARD_FORM.
Is a BADI Implementation Filter Value given for that BADI Implementation.

Irfan07_8-1781852243389.png

Irfan07_9-1781852305076.png

Schedule Condition BADI Implementation Code Below:

Action of:
BADI-EVAL_SCHEDCOND_PPF
Implementation method-IF_EX_EVAL_SCHEDCOND_PPF~EVALUATE_SCHEDULE_CONDITION


Below is the code snippet I used to Schedule the PPF Action for Email to Customer.

  METHOD if_ex_eval_schedcond_ppf~evaluate_schedule_condition.

    TYPES: BEGIN OF lty_atf_doc,
             attachment_type       TYPE /bobf/s_atf_document_k-attachment_type,
             external_link_web_uri TYPE /bobf/s_atf_document_k-external_link_web_uri,
           END OF lty_atf_doc.

    CONSTANTS: lc_email_to_cust     TYPE zi_us_tm_setleaf-setid                 VALUE 'EMAIL_TO_CUSTOMER',
               lc_freight_ord_notif TYPE /bofu/s_ppf_act-ppf_action             VALUE 'ZTM_TOR_TRACKNO_NTF',
               lc_link              TYPE /bobf/s_atf_document_k-attachment_type VALUE 'LINK',
               lc_04                TYPE /scmtms/s_tor_root_k-confirmation      VALUE '04',
               lc_05                TYPE /scmtms/s_tor_root_k-confirmation      VALUE '05'.

    CONSTANTS: lc_obj    TYPE cl_bali_header_setter=>ty_object      VALUE 'ZUS_TM_FO_LOG',
               lc_subobj TYPE cl_bali_header_setter=>ty_subobject   VALUE 'ZUS_TM_FO_PPF_LOG',
               lc_ext_id TYPE cl_bali_header_setter=>ty_external_id VALUE 'ZUS_TM_FO_PPF_ACTION_LOG'.

    DATA: lt_key             TYPE /bobf/t_frw_key,
          lt_attachment_key  TYPE /bobf/t_frw_key,
          lo_context         TYPE REF TO cl_context_ppf,
          lo_ppf_context     TYPE REF TO /bofu/cl_ppf_context,
          lt_tor_root_before TYPE /scmtms/t_tor_root_k,
          lt_tor_root_after  TYPE /scmtms/t_tor_root_k,
          lt_atf_doc_temp    TYPE STANDARD TABLE OF lty_atf_doc,
          lr_doc_status      TYPE RANGE OF /scmtms/s_tor_root_k-confirmation.

    DATA: lo_appl_log TYPE REF TO if_bali_log,
          lv_msg(200) TYPE c.

*--Default the Schedule Condition to Error.
    ep_rc = 4.

*--Log Creation Logic.
    TRY.
        lo_appl_log = cl_bali_log=>create_with_header(
                        header = cl_bali_header_setter=>create(
                                   object      = lc_obj
                                   subobject   = lc_subobj
                                   external_id = lc_ext_id ) ).
      CATCH cx_bali_runtime.
    ENDTRY.

*--MACRO for Log Messages.
    DEFINE log_free_text.
      IF lo_appl_log IS BOUND.
        TRY.
            lo_appl_log->add_item(
              item = cl_bali_free_text_setter=>create(
                       severity = &1
                       text     = &2 ) ).
          CATCH cx_bali_runtime.
        ENDTRY.
      ENDIF.
    END-OF-DEFINITION.

*--MACRO for saving the log and returning.
    DEFINE save_log_and_return.
      IF lo_appl_log IS BOUND.
        TRY.
            cl_bali_log_db=>get_instance( )->save_log( log = lo_appl_log ).
          CATCH cx_bali_runtime.
        ENDTRY.
      ENDIF.
      RETURN.
    END-OF-DEFINITION.

*--PPF Action Start Marker.
    log_free_text if_bali_constants=>c_severity_status
                  'PPF Action: Send Tracking Notification to Customer - Started'.

*--Fetch the Root Key.
    IF io_context IS BOUND.
      TRY.
          lo_context     ?= io_context.
          lo_ppf_context ?= lo_context.
          DATA(lv_root_key)    = lo_ppf_context->applkey.
        CATCH cx_sy_move_cast_error INTO DATA(lx_cast).
          log_free_text if_bali_constants=>c_severity_error
                        'PPF context cast failed (cx_sy_move_cast_error) – Cannot Proceed'.
          save_log_and_return.
        CATCH cx_sy_ref_is_initial INTO DATA(lx_ref).
          log_free_text if_bali_constants=>c_severity_error
                        'PPF context reference is initial – Cannot Proceed'.
          save_log_and_return.
        CATCH cx_root INTO DATA(lx_root_ctx).
          log_free_text if_bali_constants=>c_severity_error
                        'Unexpected error fetching PPF context – Cannot Proceed'.
          save_log_and_return.
      ENDTRY.
    ENDIF.

    APPEND INITIAL LINE TO lt_key ASSIGNING FIELD-SYMBOL(<lfs_key>).
    <lfs_key>-key = lv_root_key.

*--Service Manager Initiation.
    DATA(lo_srv_mgr) = /bobf/cl_tra_serv_mgr_factory=>get_service_manager( /scmtms/if_tor_c=>sc_bo_key ).

    CASE ip_ttype.
      WHEN lc_freight_ord_notif.  "ZTM_TOR_TRACKNO_NTF
*--------------------------------------------------------------------------
*--Validation Check Start
*--------------------------------------------------------------------------
*--Only If Tracking URL, Tracking ID & Confirmation Status is 04/05.
*--Then only trigger the email to customer.
*--Fetch the Status of the Document before Status Change.
        lo_srv_mgr->retrieve(
          EXPORTING
            iv_node_key     = /scmtms/if_tor_c=>sc_node-root
            it_key          = lt_key
            iv_before_image = abap_true
            iv_fill_data    = abap_true
          IMPORTING
            et_data         = lt_tor_root_before
            eo_message      = DATA(lo_message) ).

        IF lt_tor_root_before IS NOT INITIAL.
          DATA(lv_doc_status_before) = VALUE #( lt_tor_root_before[ 1 ]-confirmation OPTIONAL ).
        ENDIF.

*--Fetch the Status of the Document after Status Change.
        lo_srv_mgr->retrieve(
          EXPORTING
            iv_node_key  = /scmtms/if_tor_c=>sc_node-root
            it_key       = lt_key
            iv_fill_data = abap_true
          IMPORTING
            et_data      = lt_tor_root_after
            eo_message   = lo_message ).

        IF lt_tor_root_after IS NOT INITIAL.
          DATA(lv_doc_status_after) = VALUE #( lt_tor_root_after[ 1 ]-confirmation     OPTIONAL ).
          DATA(lv_purch_org)        = VALUE #( lt_tor_root_after[ 1 ]-purch_org_id     OPTIONAL ).
          DATA(lv_tracking_no)      = VALUE #( lt_tor_root_after[ 1 ]-partner_mbl_id   OPTIONAL ).
          DATA(lv_fo_no)            = VALUE #( lt_tor_root_after[ 1 ]-tor_id           OPTIONAL ).
          DATA(lv_fo) = lv_fo_no+10(10).
        ENDIF.

        TRY.
*--Fetch ATTACHMENT Folder Details.
            lo_srv_mgr->retrieve_by_association(
              EXPORTING
                iv_node_key    = /scmtms/if_tor_c=>sc_node-root
                it_key         = lt_key
                iv_association = /scmtms/if_tor_c=>sc_association-root-attachmentfolder
              IMPORTING
                et_key_link    = DATA(lt_key_link) ).

            IF lt_key_link IS NOT INITIAL.
              APPEND INITIAL LINE TO lt_attachment_key ASSIGNING FIELD-SYMBOL(<lfs_attachment_key>).
              <lfs_attachment_key>-key = lt_key_link[ 1 ]-source_key.
            ENDIF.
          CATCH /bobf/cx_frw_contrct_violation.
        ENDTRY.

*--Fetch URL & Attachment PDF Data.
        TRY.
            CALL METHOD /scmtms/cl_atf_helper=>get_atf_data
              EXPORTING
                iv_bo_key       = /scmtms/if_tor_c=>sc_bo_key
                iv_source_node  = /scmtms/if_tor_c=>sc_node-root
                iv_node         = /scmtms/if_tor_c=>sc_node-attachmentfolder
                iv_association  = /scmtms/if_tor_c=>sc_association-root-attachmentfolder
                it_key          = lt_attachment_key
              IMPORTING
                et_root         = DATA(lt_atf_root)
                et_document     = DATA(lt_atf_doc)
                et_file_content = DATA(lt_atf_file).
          CATCH cx_root INTO DATA(ls_exception).
        ENDTRY.

*--Tracking URL
        IF lt_atf_doc IS NOT INITIAL.
          lt_atf_doc_temp = CORRESPONDING #( lt_atf_doc ).
          SORT lt_atf_doc_temp BY attachment_type.

          READ TABLE lt_atf_doc_temp WITH KEY attachment_type = lc_link
          ASSIGNING FIELD-SYMBOL(<lfs_atf_doc_temp>) BINARY SEARCH.
          IF sy-subrc IS INITIAL.
            DATA(lv_tracking_url) = <lfs_atf_doc_temp>-external_link_web_uri.
          ENDIF.
        ENDIF.

        APPEND INITIAL LINE TO lr_doc_status ASSIGNING FIELD-SYMBOL(<lfs_doc_status>).
        <lfs_doc_status>-sign   = cl_abap_range=>sign-including.
        <lfs_doc_status>-option = cl_abap_range=>option-equal.
        <lfs_doc_status>-low    = lc_04.

        APPEND INITIAL LINE TO lr_doc_status ASSIGNING <lfs_doc_status>.
        <lfs_doc_status>-sign   = cl_abap_range=>sign-including.
        <lfs_doc_status>-option = cl_abap_range=>option-equal.
        <lfs_doc_status>-low    = lc_05.

*--Validation: Status not changed.
        IF lv_doc_status_before = lv_doc_status_after.
          lv_msg = |FO: { lv_fo } Status Unchanged ({ lv_doc_status_after }) – PPF action skipped|.
          log_free_text if_bali_constants=>c_severity_error lv_msg.
          save_log_and_return.
        ENDIF.

*--Validation: Status must be 04 or 05, tracking number and URL must be populated.
*--If Document Status is not Confirmed/Send to Confirmation
        IF lv_doc_status_after NOT IN lr_doc_status.
          lv_msg = |FO: { lv_fo } Document Status is not Confirmed/Send to Confirmation - Return|.
          log_free_text if_bali_constants=>c_severity_error lv_msg.
          save_log_and_return.
        ENDIF.

*--Trigger the Enhancement only If tracking number and tracking url is maintained.
        IF lv_tracking_no IS INITIAL.
          lv_msg = |Freight Order: { lv_fo } Tracking Number not found - Return|.
          log_free_text if_bali_constants=>c_severity_error lv_msg.
          save_log_and_return.
        ENDIF.

        IF lv_tracking_url IS INITIAL.
          lv_msg = |Freight Order: { lv_fo } Tracking URL not found - Return|.
          log_free_text if_bali_constants=>c_severity_error lv_msg.
          save_log_and_return.
        ENDIF.
*--------------------------------------------------------------------------
*--Validation Check End.
*--------------------------------------------------------------------------

*--Check if Purchase Org is maintained in the Control Table.
        IF lv_purch_org IS NOT INITIAL.
          SELECT SINGLE setrangefromvalue
            FROM zi_us_tm_setleaf
            WHERE setid             = @LC_email_to_cust
              AND setrangefromvalue = @LV_purch_org
            INTO @DATA(lv_value).

          IF sy-subrc IS NOT INITIAL.
            lv_msg = 'Purch Org not found in Control Table: ZI_US_TM_SETLEAF Set Id: EMAIL_TO_CUSTOMER - PPF action skipped'.
            log_free_text if_bali_constants=>c_severity_error lv_msg.
            save_log_and_return.
          ELSE.
            lv_msg = 'Purch Org validated in control table - PPF action will trigger'.
            log_free_text if_bali_constants=>c_severity_status lv_msg.
            ep_rc = 0.
          ENDIF.
        ELSE.
          log_free_text if_bali_constants=>c_severity_error
                        'Purchase Org is not maintained in ROOT - PPF action skipped'.
          save_log_and_return.
        ENDIF.

      WHEN OTHERS.
    ENDCASE.

  ENDMETHOD.

Below is the code snippet I used to Attach Attachment to the Freight Order.

  METHOD if_ex_eval_schedcond_ppf~evaluate_schedule_condition.

    TYPES: BEGIN OF lty_tor_item,
             item_cat        TYPE /scmtms/s_tor_item_tr_k-item_cat,
             main_cargo_item TYPE /scmtms/s_tor_item_tr_k-main_cargo_item,
             product_id      TYPE /scmtms/s_tor_item_tr_k-product_id,
           END OF lty_tor_item.

    CONSTANTS: lc_prd               TYPE /scmtms/s_tor_item_tr_k-item_cat VALUE 'PRD',
               lc_formname          TYPE fpname VALUE 'ZAF_US_TM_HAZARDOUS_MATERIAL',
               lc_mara              TYPE bapi1003_key-objecttable VALUE 'MARA',
               lc_matclass          TYPE bapi1003_key-classnum VALUE 'MATCLASSHZD',
               lc_classtype         TYPE bapi1003_key-classtype VALUE '001',
               lc_hazard            TYPE zi_us_tm_setleaf-setid VALUE 'HAZARDOUS_FORM',
               lc_hazard_form_attch TYPE /bofu/s_ppf_act-ppf_action VALUE 'ZTM_TOR_HAZARD_FORM',
               lc_mimetype          TYPE /bobf/s_atf_a_create_file-mime_code VALUE 'application/pdf',
               lc_atcmt             TYPE /bobf/s_atf_a_create_file-attachment_type VALUE 'ATCMT',
               lc_default           TYPE /bobf/s_atf_a_create_file-attachment_schema VALUE 'DEFAULT',
               lc_mercury           TYPE bapi1003_alloc_values_char-value_char VALUE 'MERCURY',
               lc_char_desc         TYPE bapi1003_alloc_values_char-charact_descr VALUE 'MERCURY OR PERCHLORAT'.

    CONSTANTS: lc_04 TYPE /scmtms/s_tor_root_k-confirmation VALUE '04',
               lc_05 TYPE /scmtms/s_tor_root_k-confirmation VALUE '05'.

    DATA: lt_key             TYPE /bobf/t_frw_key,
          lt_tor_root_before TYPE /scmtms/t_tor_root_k,
          lt_tor_root_after  TYPE /scmtms/t_tor_root_k,
          lo_context         TYPE REF TO cl_context_ppf,
          lo_ppf_context     TYPE REF TO /bofu/cl_ppf_context,
          lr_doc_status      TYPE RANGE OF /scmtms/s_tor_root_k-confirmation.

    DATA: lv_fm_name      TYPE rs38l_fnam,
          ls_outputparams TYPE sfpoutputparams,
          ls_docparams    TYPE sfpdocparams,
          ls_result       TYPE sfpjoboutput,
          ls_formoutput   TYPE fpformoutput.

    DATA: lt_atf_key       TYPE /bobf/t_frw_key,
          lt_failed_key    TYPE /bobf/t_frw_key,
          lt_tor_item      TYPE /scmtms/t_tor_item_tr_k,
          lt_tor_item_temp TYPE STANDARD TABLE OF lty_tor_item,
          lt_mod           TYPE /bobf/t_frw_modification,
          ls_mod           TYPE /bobf/s_frw_modification,
          lv_rejected      TYPE boole_d,
          lv_action_key    TYPE /bobf/conf_key,
          lv_tor_key       TYPE /bobf/conf_key,
          ls_parameters    TYPE /bobf/s_atf_a_create_file,
          lr_action_par    TYPE REF TO /bobf/s_atf_a_create_file,
          lr_atf_root      TYPE REF TO /bobf/s_atf_root_k.

    DATA: lt_allocvalueschar TYPE TABLE OF bapi1003_alloc_values_char,
          lt_allocvaluesnum  TYPE TABLE OF bapi1003_alloc_values_num,
          lt_allocvaluescurr TYPE TABLE OF bapi1003_alloc_values_curr,
          lt_return_cls      TYPE TABLE OF bapiret2.

    ep_rc = 4.

*--Fetch the Root Key.
    IF io_context IS BOUND.
      TRY.
          lo_context       ?= io_context.
          lo_ppf_context   ?= lo_context.
          DATA(lv_root_key) = lo_ppf_context->applkey.
        CATCH /bobf/cx_frw_contrct_violation.
          RETURN.
        CATCH cx_root.
          RETURN.
      ENDTRY.
    ENDIF.

    APPEND INITIAL LINE TO lt_key ASSIGNING FIELD-SYMBOL(<lfs_key>).
    <lfs_key>-key = lv_root_key.

*--Invoke Service Manger & Transaction Manager.
    TRY.
        DATA(lo_srv_tor) = /bobf/cl_tra_serv_mgr_factory=>get_service_manager( /scmtms/if_tor_c=>sc_bo_key ).
        DATA(lo_tra_tor) = /bobf/cl_tra_trans_mgr_factory=>get_transaction_manager( ).
      CATCH /bobf/cx_frw_contrct_violation.
        RETURN.
      CATCH cx_root.
        RETURN.
    ENDTRY.

    CASE ip_ttype.
      WHEN lc_hazard_form_attch.    "ZTM_TOR_HAZARD_FORM
* =========================================================================
* PART 1: Validation Check for Enhancement Check & Hazardous Material Check
* =========================================================================
*--TOR Root Details before Status Change.
        TRY.
            lo_srv_tor->retrieve(
              EXPORTING
                iv_node_key     = /scmtms/if_tor_c=>sc_node-root
                it_key          = lt_key
                iv_before_image = abap_true
                iv_fill_data    = abap_true
              IMPORTING
                et_data         = lt_tor_root_before
                eo_message      = DATA(lo_message) ).

            IF lt_tor_root_before IS NOT INITIAL.
              DATA(lv_doc_status_before)  = VALUE #( lt_tor_root_before[ 1 ]-confirmation OPTIONAL ).
            ENDIF.

*--TOR Root Details after Status Change.
            lo_srv_tor->retrieve(
              EXPORTING
                iv_node_key  = /scmtms/if_tor_c=>sc_node-root
                it_key       = lt_key
                iv_fill_data = abap_true
              IMPORTING
                et_data      = lt_tor_root_after
                eo_message   = lo_message ).

            IF lt_tor_root_after IS NOT INITIAL.
              DATA(lv_purch_org)        = VALUE #( lt_tor_root_after[ 1 ]-purch_org_id OPTIONAL ).
              DATA(lv_doc_status_after) = VALUE #( lt_tor_root_after[ 1 ]-confirmation OPTIONAL ).

              APPEND INITIAL LINE TO lr_doc_status ASSIGNING FIELD-SYMBOL(<lfs_doc_status>).
              <lfs_doc_status>-sign   = cl_abap_range=>sign-including.
              <lfs_doc_status>-option = cl_abap_range=>option-equal.
              <lfs_doc_status>-low    = lc_04.

              APPEND INITIAL LINE TO lr_doc_status ASSIGNING <lfs_doc_status>.
              <lfs_doc_status>-sign   = cl_abap_range=>sign-including.
              <lfs_doc_status>-option = cl_abap_range=>option-equal.
              <lfs_doc_status>-low    = lc_05.

*--If the Freight Order Status is not 04/05 Enhancement not applicable.

              IF lv_doc_status_before = lv_doc_status_after.
                RETURN.
              ENDIF.

              IF lv_doc_status_after NOT IN lr_doc_status.
                RETURN.
              ENDIF.

*--Read the SET value from Enhancement Control Table.
*--If Purchase Org Not Present in the Enh. Control Table Enhancement not applicable.
              IF lv_purch_org IS NOT INITIAL.
                SELECT SINGLE setrangefromvalue
                FROM zi_us_tm_setleaf
                WHERE setid           = @LC_hazard         "HAZARDOUS_FORM
                AND setrangefromvalue = @LV_purch_org
                INTO @DATA(lv_plant).
                IF sy-subrc IS NOT INITIAL.
                  RETURN.
                ENDIF.

*--Fetch Item Details.
                lo_srv_tor->retrieve_by_association(
                  EXPORTING
                    iv_node_key    = /scmtms/if_tor_c=>sc_node-root
                    it_key         = lt_key
                    iv_association = /scmtms/if_tor_c=>sc_association-root-item_tr
                    iv_fill_data   = abap_true
                    iv_edit_mode   = /bobf/if_conf_c=>sc_edit_read_only
                  IMPORTING
                    et_data        = lt_tor_item
                    eo_message     = lo_message ).

                IF lt_tor_item IS NOT INITIAL.
                  lt_tor_item_temp = CORRESPONDING #( lt_tor_item ).
                  SORT lt_tor_item_temp BY item_cat main_cargo_item.

                  IF lt_tor_item_temp IS NOT INITIAL.
                    READ TABLE lt_tor_item_temp WITH KEY item_cat = lc_prd main_cargo_item = abap_true
                    ASSIGNING FIELD-SYMBOL(<lfs_tor_item_temp>) BINARY SEARCH.
                    IF sy-subrc IS INITIAL.
                      DATA(lv_product) = <lfs_tor_item_temp>-product_id.
                    ENDIF.
                  ENDIF.
                ENDIF.

*--Get Material Classification Details.
                IF lv_product IS NOT INITIAL.
                  CALL FUNCTION 'BAPI_OBJCL_GETDETAIL'
                    EXPORTING
                      objectkey       = CONV bapi1003_key-object( lv_product )
                      objecttable     = lc_mara       "'MARA'
                      classnum        = lc_matclass   "'MATCLASSHZD'
                      classtype       = lc_classtype  "'001'
                    TABLES
                      allocvaluesnum  = lt_allocvaluesnum
                      allocvalueschar = lt_allocvalueschar
                      allocvaluescurr = lt_allocvaluescurr
                      return          = lt_return_cls.

                  SORT lt_return_cls BY type.
                  READ TABLE lt_return_cls WITH KEY type = 'S' TRANSPORTING NO FIELDS BINARY SEARCH.
                  IF sy-subrc IS NOT INITIAL.
                    RETURN.
                  ENDIF.

*--If there is NO Hazardous Material RETURN.
                  SORT lt_allocvalueschar BY charact_descr.

                  READ TABLE lt_allocvalueschar INTO DATA(ls_hazard_cls)
                  WITH KEY charact_descr = lc_char_desc BINARY SEARCH.
                  IF sy-subrc IS INITIAL.
                    DATA(lv_hazard_type) = ls_hazard_cls-value_char.
                    IF lv_hazard_type <> lc_mercury.    "'MERCURY'.
                      RETURN.
                    ENDIF.
                  ENDIF.

                ENDIF.

              ENDIF.
            ENDIF.
          CATCH /bobf/cx_frw_contrct_violation.
            RETURN.
          CATCH cx_root.
            RETURN.
        ENDTRY.

*--Fetch Company Address
        IF lv_purch_org IS NOT INITIAL.
          SELECT SINGLE b~addressid
          FROM zi_us_tm_hrp5561 AS a
          INNER JOIN i_buspartaddress AS b
          ON b~businesspartner = a~partner
          WHERE a~objid = @LV_purch_org
          INTO @DATA(lv_adrs).
        ENDIF.

* =====================================================================
* PART 2: Create the Hazard Warning Adobe Form
* =====================================================================
        ls_outputparams-nodialog = abap_true.
        ls_outputparams-getpdf   = abap_true.

        ls_docparams-langu   = sy-langu.

        CALL FUNCTION 'FP_JOB_OPEN'
          CHANGING
            ie_outputparams = ls_outputparams
          EXCEPTIONS
            cancel          = 1
            usage_error     = 2
            system_error    = 3
            internal_error  = 4
            OTHERS          = 5.
        IF sy-subrc IS INITIAL.
          TRY.
              CALL FUNCTION 'FP_FUNCTION_MODULE_NAME'
                EXPORTING
                  i_name     = lc_formname  "'ZAF_US_TM_HAZARDOUS_MATERIAL'
                IMPORTING
                  e_funcname = lv_fm_name.
            CATCH cx_fp_api_repository cx_fp_api_usage cx_fp_api_internal.
          ENDTRY.

          CALL FUNCTION lv_fm_name
            EXPORTING
              /1bcdwb/docparams  = ls_docparams
              iv_addrs_number    = lv_adrs
            IMPORTING
              /1bcdwb/formoutput = ls_formoutput
            EXCEPTIONS
              usage_error        = 1
              system_error       = 2
              internal_error     = 3
              OTHERS             = 4.
          IF sy-subrc IS INITIAL.
            CALL FUNCTION 'FP_JOB_CLOSE'
              IMPORTING
                e_result       = ls_result
              EXCEPTIONS
                usage_error    = 1
                system_error   = 2
                internal_error = 3
                OTHERS         = 4.

            IF sy-subrc IS INITIAL AND ls_formoutput-pdf IS NOT INITIAL.
              DATA(lv_pdf_xstring) = ls_formoutput-pdf.
            ENDIF.
          ENDIF.
        ENDIF.

* =====================================================================
* PART 3: Attach PDF to Freight Order - Separate Save
* =====================================================================
        IF lv_pdf_xstring IS NOT INITIAL.

          ep_rc = 0.

*--Call the Attachment Add Logic with the Save sequence in separate task.
          CALL FUNCTION 'Z_US_TM_FO_EMAIL_NOTIFICATION' STARTING NEW TASK 'Z_US_TM_FO_EMAIL_NOTIFICATION'
            EXPORTING
              iv_root_key = lv_root_key
              iv_pdf_data = lv_pdf_xstring.

        ENDIF.

      WHEN OTHERS.
    ENDCASE.

  ENDMETHOD.

 
Code of the FM: Z_US_TM_FO_EMAIL_NOTIFICATION.

FUNCTION z_us_tm_fo_email_notification.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(IV_ROOT_KEY) TYPE  /BOBF/CONF_KEY
*"     VALUE(IV_PDF_DATA) TYPE  FPCONTENT
*"----------------------------------------------------------------------

  CONSTANTS: lc_mimetype TYPE /bobf/s_atf_a_create_file-mime_code VALUE 'application/pdf',
             lc_atcmt    TYPE /bobf/s_atf_a_create_file-attachment_type VALUE 'ATCMT',
             lc_default  TYPE /bobf/s_atf_a_create_file-attachment_schema VALUE 'DEFAULT'.

  DATA: lt_key        TYPE /bobf/t_frw_key,
        ls_parameters TYPE /bobf/s_atf_a_create_file,
        lr_action_par TYPE REF TO /bobf/s_atf_a_create_file,
        lr_atf_root   TYPE REF TO /bobf/s_atf_root_k,
        lt_mod        TYPE /bobf/t_frw_modification,
        ls_mod        TYPE /bobf/s_frw_modification.

  APPEND INITIAL LINE TO lt_key ASSIGNING FIELD-SYMBOL(<lfs_key>).
  <lfs_key>-key = iv_root_key.

*--Invoke Service Manger & Transaction Manager.
  TRY.
      DATA(lo_srv_tor) = /bobf/cl_tra_serv_mgr_factory=>get_service_manager( /scmtms/if_tor_c=>sc_bo_key ).
      DATA(lo_tra_tor) = /bobf/cl_tra_trans_mgr_factory=>get_transaction_manager( ).
    CATCH /bobf/cx_frw_contrct_violation.
      RETURN.
    CATCH cx_root.
      RETURN.
  ENDTRY.

*--Fetch the ATTACHMENTFOLDER key.
  TRY.
      lo_srv_tor->retrieve_by_association(
        EXPORTING
          iv_node_key    = /scmtms/if_tor_c=>sc_node-root
          it_key         = lt_key
          iv_association = /scmtms/if_tor_c=>sc_association-root-attachmentfolder
          iv_edit_mode   = /bobf/if_conf_c=>sc_edit_read_only
        IMPORTING
          et_target_key  = DATA(lt_atf_key)
          et_failed_key  = DATA(lt_failed_key) ).
    CATCH /bobf/cx_frw_contrct_violation.
      RETURN.
    CATCH cx_root.
      RETURN.
  ENDTRY.

*--If the ATTACHMENTFOLDER is blank and there is NO Attachment attached to it.
*--Create the Folder First.
  IF lt_atf_key IS INITIAL.

    TRY.
        CREATE DATA lr_atf_root.
        lr_atf_root->key        = lo_srv_tor->get_new_key( ).
        lr_atf_root->parent_key = /scmtms/if_tor_c=>sc_node-root.

        ls_mod-change_mode = /bobf/if_frw_c=>sc_modify_create.
        ls_mod-association = /scmtms/if_tor_c=>sc_association-root-attachmentfolder.
        ls_mod-source_node = /scmtms/if_tor_c=>sc_node-root.
        ls_mod-node        = /scmtms/if_tor_c=>sc_node-attachmentfolder.
        ls_mod-source_key  = iv_root_key.
        ls_mod-key         = lr_atf_root->key.
        ls_mod-data        = lr_atf_root.
        INSERT ls_mod INTO TABLE lt_mod.

        lo_srv_tor->modify(
          EXPORTING
            it_modification = lt_mod
          IMPORTING
            eo_change       = DATA(lo_change)
            eo_message      = DATA(lo_message) ).

***        lo_tra_tor->save(
***          IMPORTING
***            ev_rejected         = DATA(lv_rejected)
***            eo_change           = lo_change
***            eo_message          = lo_message ).

        INSERT VALUE #( key = lr_atf_root->key ) INTO TABLE lt_atf_key.

      CATCH /bobf/cx_frw_contrct_violation.
        RETURN.
      CATCH cx_root.
        RETURN.
    ENDTRY.

  ENDIF.

*--Populate the Attachment Details.
  ls_parameters-file_name                 = 'Hazardous Material Information.pdf'(001).
  ls_parameters-alternative_name          = 'Hazardous Material Information.pdf'(001).
  ls_parameters-name                      = 'Hazardous Material Information.pdf'(001).
  ls_parameters-content                   = iv_pdf_data.
  ls_parameters-mime_code                 = lc_mimetype.       "'application/pdf'.
  ls_parameters-description_language_code = sy-langu.
  ls_parameters-description               = 'Hazardous Material Information.pdf'(001).
  ls_parameters-description_content       = 'Hazardous Material Information.pdf'(001).
  ls_parameters-visibility_type           = abap_true.
  ls_parameters-attachment_type           = lc_atcmt.          "'ATCMT'.
  ls_parameters-attachment_schema         = lc_default.        "'DEFAULT'.

  GET REFERENCE OF ls_parameters INTO lr_action_par.

  TRY.
      /scmtms/cl_common_helper=>get_do_keys_4_action(
        EXPORTING
          iv_host_bo_key      = /scmtms/if_tor_c=>sc_bo_key
          iv_host_do_node_key = /scmtms/if_tor_c=>sc_node-attachmentfolder
          iv_do_action_key    = /bobf/if_attachment_folder_c=>sc_action-root-create_file
        IMPORTING
          ev_action_key       = DATA(lv_action_key) ).
    CATCH /bobf/cx_frw_contrct_violation.
      RETURN.
    CATCH cx_root.
      RETURN.
  ENDTRY.

  IF lv_action_key IS INITIAL.
    RETURN.
  ENDIF.

  TRY.
      lo_srv_tor->do_action(
        EXPORTING
          iv_act_key    = lv_action_key
          it_key        = lt_atf_key
          is_parameters = lr_action_par
        IMPORTING
          et_failed_key = DATA(lt_failed_key_atf)
          eo_change     = lo_change
          eo_message    = lo_message ).

      lo_tra_tor->save(
        IMPORTING
          ev_rejected         = DATA(lv_rejected)
          eo_change           = lo_change
          eo_message          = lo_message ).

    CATCH /bobf/cx_frw_contrct_violation.
      RETURN.
    CATCH cx_root.
      RETURN.
  ENDTRY.

ENDFUNCTION.


Note:
I had added the create attachment logic in a RFC Function Module and called it from PPF-Schedule Action BADI Implementation method STARTING NEW TASK.
As, the BADI implementation won't allow explicit SAVE.


9. Similarly for Start Condition as well.

Irfan07_10-1781852425453.png

Irfan07_11-1781852456794.png

Irfan07_12-1781852533085.png

Inside the Badi Impl we set the flags to value "4" if our conditions not met.

Irfan07_13-1781852613550.png

10. Maintain Entry in Schedule Condition.

Irfan07_14-1781852696899.png

Irfan07_15-1781852755208.png

11. Create a child class of Standard class: /SCMTMS/CL_PPF_SERV_TOR_B2B

Irfan_Md_0-1782833686609.png

Redefine your required methods.

Irfan_Md_1-1782833731576.png

Irfan_Md_2-1782833774767.png

METHOD method_call_by_abap.
*--------------------------------------------------------------------------
*--Types Declaration
*--------------------------------------------------------------------------
    TYPES: BEGIN OF lty_docref_data,
             btd_tco TYPE /scmtms/s_tor_docref_k-btd_tco,
             btd_id  TYPE /scmtms/s_tor_docref_k-btd_id,
           END OF lty_docref_data,

           BEGIN OF lty_stop_data,
             stop_seq_pos    TYPE /scmtms/s_tor_stop_k-stop_seq_pos,
             plan_trans_time TYPE /scmtms/s_tor_stop_k-plan_trans_time,
           END OF lty_stop_data,

           BEGIN OF lty_tor_item,
             item_cat         TYPE /scmtms/s_tor_item_tr_k-item_cat,
             main_cargo_item  TYPE /scmtms/s_tor_item_tr_k-main_cargo_item,
             loading_point_id TYPE /scmtms/s_tor_item_tr_k-loading_point_id,
           END OF lty_tor_item,

           BEGIN OF lty_soldtoparty,
             party_rco TYPE /scmtms/s_tor_party_k-party_rco,
             party_id  TYPE /scmtms/s_tor_party_k-party_id,
           END OF lty_soldtoparty,

           BEGIN OF lty_atf_doc,
             attachment_type       TYPE /bobf/s_atf_document_k-attachment_type,
             external_link_web_uri TYPE /bobf/s_atf_document_k-external_link_web_uri,
           END OF lty_atf_doc.

*--------------------------------------------------------------------------
*--Data Declaration & Constants
*--------------------------------------------------------------------------
    CONSTANTS: lc_pdf           TYPE soodk-objtp                            VALUE 'PDF',
               lc_type          TYPE w3conttype                             VALUE 'image/bmp',
               lc_set           TYPE i_setleaf-setid                        VALUE 'EMAIL_TO_CUSTOMER',
               lc_73            TYPE /scmtms/s_tor_docref_k-btd_tco         VALUE '73',
               lc_114           TYPE /scmtms/s_tor_docref_k-btd_tco         VALUE '114',
               lc_prd           TYPE /scmtms/s_tor_item_tr_k-item_cat       VALUE 'PRD',
               lc_sp            TYPE /scmtms/s_tor_party_k-party_rco        VALUE 'AG',
               lc_us_tm004      TYPE zi_tvarvctableforcusto-changeid        VALUE 'US_TM004',
               lc_04            TYPE /scmtms/s_tor_root_k-confirmation      VALUE '04',
               lc_05            TYPE /scmtms/s_tor_root_k-confirmation      VALUE '05',
               lc_l             TYPE /scmtms/s_tor_stop_k-stop_seq_pos      VALUE 'L',
               lc_comp1          TYPE zi_us_tm_setleaf-setrangefromvalue     VALUE '500001',
               lc_comp2          TYPE zi_us_tm_setleaf-setrangefromvalue     VALUE '500002',
               lc_email_trigger TYPE /bofu/s_ppf_act-ppf_action             VALUE 'ZTM_TOR_TRACKNO_NTF',
               lc_hazard_form   TYPE /bofu/s_ppf_act-ppf_action             VALUE 'ZTM_TOR_HAZARD_FORM',
               lc_name1       TYPE zi_tvarvctableforcusto-name            VALUE 'Z_EMAIL1',
               lc_name2       TYPE zi_tvarvctableforcusto-name            VALUE 'Z_EMAIL2',
               lc_mimetype      TYPE /bobf/s_atf_file_content_k-mime_code   VALUE 'application/pdf',
               lc_link          TYPE /bobf/s_atf_document_k-attachment_type VALUE 'LINK'.

    CONSTANTS: lc_company1 TYPE tdobname   VALUE 'ZCOMPANY1_LOGO',
               lc_company2 TYPE tdobname   VALUE 'ZCOMPANY2_LOGO',
               lc_graphics  TYPE tdobjectgr VALUE 'GRAPHICS',
               lc_bmap      TYPE tdidgr     VALUE 'BMAP',
               lc_bcol      TYPE tdbtype    VALUE 'BCOL'.

    CONSTANTS: lc_obj    TYPE cl_bali_header_setter=>ty_object      VALUE 'ZTM_FO_LOG',
               lc_subobj TYPE cl_bali_header_setter=>ty_subobject   VALUE 'ZTM_FO_PPF_LOG',
               lc_ext_id TYPE cl_bali_header_setter=>ty_external_id VALUE 'ZTM_FO_PPF_ACTION_LOG'.

    DATA: lt_docref_data_temp TYPE STANDARD TABLE OF lty_docref_data,
          lt_stop_data_temp   TYPE STANDARD TABLE OF lty_stop_data,
          lt_tor_item_temp    TYPE STANDARD TABLE OF lty_tor_item,
          lt_soldtoparty_temp TYPE STANDARD TABLE OF lty_soldtoparty,
          lt_atf_doc_temp     TYPE STANDARD TABLE OF lty_atf_doc.

    DATA: lv_html      TYPE string,
          lv_html_item TYPE string.

    DATA: lt_attachment_key  TYPE /bobf/t_frw_key,
          lt_key             TYPE /bobf/t_frw_key,
          lt_stop_data       TYPE /scmtms/t_tor_stop_k,
          lt_tor_root_before TYPE /scmtms/t_tor_root_k,
          lt_tor_root_after  TYPE /scmtms/t_tor_root_k,
          lt_soldtoparty     TYPE /scmtms/t_tor_party_k,
          lt_docref_data     TYPE /scmtms/t_tor_docref_k,
          lt_tor_item        TYPE /scmtms/t_tor_item_tr_k,
          lv_sales_order     TYPE i_salesdocument-salesdocument,
          lv_delv_doc        TYPE i_deliverydocument-deliverydocument,
          lv_ship_date       TYPE string,
          lv_temp_date       TYPE string,
          ls_addrs_sel       TYPE addr1_sel,
          lv_qty             TYPE p DECIMALS 2.

    DATA: lv_hama_logo    TYPE xstring,
          lv_ener_logo    TYPE xstring,
          lv_company_logo TYPE string,
          lv_root_key     TYPE /bobf/conf_key,
          lv_read_key     TYPE char25,
          lo_container    TYPE REF TO /bofu/cl_ppf_container,
          lo_message      TYPE REF TO /bobf/if_frw_message,
          lr_name         TYPE RANGE OF zi_tvarvctableforcusto-name,
          lr_doc_status   TYPE RANGE OF /scmtms/s_tor_root_k-confirmation.

    DATA: lv_attach_size TYPE sood-objlen,
          lv_file_name   TYPE sood-objdes,
          ls_html_body   TYPE soli,
          ls_logo_solix  TYPE solix,
          lt_binary_tab  TYPE solix_tab,
          lt_html_body   TYPE soli_tab.

    DATA: lo_appl_log TYPE REF TO if_bali_log,
          lv_msg(200) TYPE c.

*--Log Creation Logic.
    TRY.
        lo_appl_log = cl_bali_log=>create_with_header(
                        header = cl_bali_header_setter=>create(
                                   object      = lc_obj
                                   subobject   = lc_subobj
                                   external_id = lc_ext_id ) ).
      CATCH cx_bali_runtime.
    ENDTRY.

*--MACRO for Log Messages.
    DEFINE log_free_text.
      IF lo_appl_log IS BOUND.
        TRY.
            lo_appl_log->add_item(
              item = cl_bali_free_text_setter=>create(
                       severity = &1
                       text     = &2 ) ).
          CATCH cx_bali_runtime.
        ENDTRY.
      ENDIF.
    END-OF-DEFINITION.

*--MACRO for saving the log and returning.
    DEFINE save_log_and_return.
      IF lo_appl_log IS BOUND.
        TRY.
            cl_bali_log_db=>get_instance( )->save_log( log = lo_appl_log ).
          CATCH cx_bali_runtime.
        ENDTRY.
      ENDIF.
      RETURN.
    END-OF-DEFINITION.

*--Get the BO Root Key.
    TRY.
        IF io_container IS BOUND.
          lo_container ?= io_container.
          lv_root_key = lo_container->get_bo_root_key( ).
        ENDIF.
      CATCH: cx_sy_move_cast_error cx_sy_ref_is_initial cx_root.
    ENDTRY.

    APPEND INITIAL LINE TO lt_key ASSIGNING FIELD-SYMBOL(<lfs_key>).
    <lfs_key>-key = lv_root_key.

*--Service Manager Initiation.
    DATA(lo_srv_mgr) = /bobf/cl_tra_serv_mgr_factory=>get_service_manager( /scmtms/if_tor_c=>sc_bo_key ).

    CASE is_ppf_act-ppf_action.

      WHEN lc_email_trigger.   "ZTM_TOR_TRACKNO_NTF

*--------------------------------------------------------------------------
*--Validation Check Start
*--------------------------------------------------------------------------
        TRY.
*--Only If Tracking URL, Tracking ID & Confirmation Status is 04/05.
*--Then only trigger the email to customer.
*--Fetch the Status of the Document before Status Change.
            lo_srv_mgr->retrieve(
              EXPORTING
                iv_node_key     = /scmtms/if_tor_c=>sc_node-root
                it_key          = lt_key
                iv_before_image = abap_true
                iv_fill_data    = abap_true
              IMPORTING
                et_data         = lt_tor_root_before
                eo_message      = lo_message ).

            IF lt_tor_root_before IS NOT INITIAL.
              DATA(lv_doc_status_before) = VALUE #( lt_tor_root_before[ 1 ]-confirmation OPTIONAL ).
            ENDIF.

*--Fetch the Status of the Document after Status Change.
            lo_srv_mgr->retrieve(
              EXPORTING
                iv_node_key  = /scmtms/if_tor_c=>sc_node-root
                it_key       = lt_key
                iv_fill_data = abap_true
              IMPORTING
                et_data      = lt_tor_root_after
                eo_message   = lo_message ).

            IF lt_tor_root_after IS NOT INITIAL.

              DATA(lv_doc_status_after) = VALUE #( lt_tor_root_after[ 1 ]-confirmation     OPTIONAL ).
              DATA(lv_tracking_no)      = VALUE #( lt_tor_root_after[ 1 ]-partner_mbl_id   OPTIONAL ).
              DATA(lv_carrier)          = VALUE #( lt_tor_root_after[ 1 ]-tspid            OPTIONAL ).
              DATA(lv_terms)            = VALUE #( lt_tor_root_after[ 1 ]-transsrvlvl_code OPTIONAL ).
              DATA(lv_consignee_id)     = VALUE #( lt_tor_root_after[ 1 ]-consigneeid      OPTIONAL ).
              DATA(lv_purch_orgid)      = VALUE #( lt_tor_root_after[ 1 ]-purch_org_id     OPTIONAL ).

              IF lv_purch_orgid IS NOT INITIAL.
                SELECT SINGLE setrangefromvalue
                FROM zi_us_tm_setleaf
                WHERE setid           = @lc_set         "'EMAIL_TO_CUSTOMER'
                AND setrangefromvalue = @lv_purch_orgid
                INTO @DATA(lv_purch_org).

                IF sy-subrc IS NOT INITIAL.
                  lv_msg = |Purch Org: { lv_purch_orgid } not maintained in Table: ZI_US_TM_SETLEAF| &&
                           |Set-Id: EMAIL_TO_CUSTOMER.|.
                  log_free_text if_bali_constants=>c_severity_status lv_msg.
                  rp_status = 2.
                  save_log_and_return.
                ENDIF.

              ENDIF.
            ENDIF.
          CATCH /bobf/cx_frw_contrct_violation.
        ENDTRY.

*--Fetch ATTACHMENT Folder Details.
        TRY.
            lo_srv_mgr->retrieve_by_association(
              EXPORTING
                iv_node_key    = /scmtms/if_tor_c=>sc_node-root
                it_key         = lt_key
                iv_association = /scmtms/if_tor_c=>sc_association-root-attachmentfolder
              IMPORTING
                et_key_link   = DATA(lt_key_link)
                et_target_key = DATA(lt_target_key)
                et_failed_key = DATA(lt_failed_key) ).

            IF lt_key_link IS NOT INITIAL.
              APPEND INITIAL LINE TO lt_attachment_key ASSIGNING FIELD-SYMBOL(<lfs_attachment_key>).
              <lfs_attachment_key>-key = lt_key_link[ 1 ]-source_key.
            ENDIF.
          CATCH /bobf/cx_frw_contrct_violation.
        ENDTRY.

*--Fetch URL & Attachment PDF Data.
        TRY.
            CALL METHOD /scmtms/cl_atf_helper=>get_atf_data
              EXPORTING
                iv_bo_key       = /scmtms/if_tor_c=>sc_bo_key
                iv_source_node  = /scmtms/if_tor_c=>sc_node-root
                iv_node         = /scmtms/if_tor_c=>sc_node-attachmentfolder
                iv_association  = /scmtms/if_tor_c=>sc_association-root-attachmentfolder
                it_key          = lt_attachment_key
              IMPORTING
                et_root         = DATA(lt_atf_root)
                et_document     = DATA(lt_atf_doc)
                et_file_content = DATA(lt_atf_file).
          CATCH cx_root INTO DATA(ls_exception).
        ENDTRY.

*--Tracking URL
        IF lt_atf_doc IS NOT INITIAL.
          lt_atf_doc_temp = CORRESPONDING #( lt_atf_doc ).
          SORT lt_atf_doc_temp BY attachment_type.

          READ TABLE lt_atf_doc_temp WITH KEY attachment_type = lc_link
          ASSIGNING FIELD-SYMBOL(<lfs_atf_doc_temp>) BINARY SEARCH.
          IF sy-subrc IS INITIAL.
            DATA(lv_tracking_url) = <lfs_atf_doc_temp>-external_link_web_uri.
          ENDIF.
        ENDIF.

        APPEND INITIAL LINE TO lr_doc_status ASSIGNING FIELD-SYMBOL(<lfs_doc_status>).
        <lfs_doc_status>-sign   = cl_abap_range=>sign-including.
        <lfs_doc_status>-option = cl_abap_range=>option-equal.
        <lfs_doc_status>-low    = lc_04.

        APPEND INITIAL LINE TO lr_doc_status ASSIGNING <lfs_doc_status>.
        <lfs_doc_status>-sign   = cl_abap_range=>sign-including.
        <lfs_doc_status>-option = cl_abap_range=>option-equal.
        <lfs_doc_status>-low    = lc_05.

*--If Document Status is Unchanged RETURN the Control.
        IF lv_doc_status_before = lv_doc_status_after.
          lv_msg = |Document Status Unchanged - Return|.
          log_free_text if_bali_constants=>c_severity_error lv_msg.
          rp_status = 2.
          save_log_and_return.
        ENDIF.

*--If Document Status is not Confirmed/Send to Confirmation
        IF lv_doc_status_after NOT IN lr_doc_status.
          lv_msg = |Document Status is not Confirmed/Send to Confirmation - Return|.
          log_free_text if_bali_constants=>c_severity_error lv_msg.
          rp_status = 2.
          save_log_and_return.
        ENDIF.

*--Trigger the Enhancement only If tracking number and tracking url is maintained.
        IF lv_tracking_no IS INITIAL.
          lv_msg = |Freight Order Tracking Number not found - Return|.
          log_free_text if_bali_constants=>c_severity_error lv_msg.
          rp_status = 2.
          save_log_and_return.
        ENDIF.

        IF lv_tracking_url IS INITIAL.
          lv_msg = |Freight Order Tracking URL not found - Return|.
          log_free_text if_bali_constants=>c_severity_error lv_msg.
          rp_status = 2.
          save_log_and_return.
        ENDIF.

*--------------------------------------------------------------------------
*--Validation Check End.
*--------------------------------------------------------------------------
        TRY.
*--Fetch Sales Order & Delivery Number Document
            lo_srv_mgr->retrieve_by_association(
              EXPORTING
                iv_node_key    = /scmtms/if_tor_c=>sc_node-root
                it_key         = lt_key
                iv_association = /scmtms/if_tor_c=>sc_association-root-docreference
                iv_fill_data   = abap_true
                iv_edit_mode   = /bobf/if_conf_c=>sc_edit_read_only
              IMPORTING
                et_data        = lt_docref_data
                et_target_key  = DATA(lt_target_keys)
                et_key_link    = DATA(lt_key_links)
                eo_message     = lo_message ).

            IF lt_docref_data IS NOT INITIAL.
              lt_docref_data_temp = CORRESPONDING #( lt_docref_data ).
              SORT lt_docref_data_temp BY btd_tco.
              READ TABLE lt_docref_data_temp WITH KEY btd_tco = lc_114 INTO DATA(ls_docref) BINARY SEARCH.
              IF sy-subrc IS INITIAL.
                DATA(lv_so_no) = ls_docref-btd_id.
              ENDIF.

              READ TABLE lt_docref_data_temp WITH KEY btd_tco = lc_73 INTO ls_docref BINARY SEARCH.
              IF sy-subrc IS INITIAL.
                DATA(lv_delv_no) = ls_docref-btd_id.
              ENDIF.

*--Fetch Delivery Document Details
              IF lv_delv_no IS NOT INITIAL.
                lv_delv_doc = lv_delv_no+25(10).
                SELECT SINGLE a~deliverydocument,a~documentdate,a~shippingcondition,
                              b~materialbycustomer,b~actualdeliveryquantity,
                              c~shippingconditionname
                FROM i_deliverydocument AS a
                INNER JOIN i_deliverydocumentitem AS b
                ON b~deliverydocument = b~deliverydocument
                INNER JOIN i_shippingconditiontext AS c
                ON c~shippingcondition = a~shippingcondition
                WHERE a~deliverydocument = @lv_delv_doc
                INTO @DATA(ls_delv_det).
                IF sy-subrc IS NOT INITIAL.
                  CLEAR: ls_delv_det.
                ENDIF.
              ENDIF.

*--Fetch Purchase Order Number.
              IF lv_so_no IS NOT INITIAL.
                lv_sales_order = lv_so_no+25(10).

                SELECT SINGLE purchaseorderbycustomer
                FROM i_salesdocument
                WHERE salesdocument = @lv_sales_order
                INTO @DATA(lv_po_no).
                IF sy-subrc IS NOT INITIAL.
                  CLEAR: lv_po_no.
                ENDIF.

              ENDIF.
            ENDIF.
          CATCH /bobf/cx_frw_contrct_violation.
        ENDTRY.

        TRY.
*--Shipment Date
            lo_srv_mgr->retrieve_by_association(
              EXPORTING
                iv_node_key    = /scmtms/if_tor_c=>sc_node-root
                it_key         = lt_key
                iv_association = /scmtms/if_tor_c=>sc_association-root-stop
                iv_fill_data   = abap_true
                iv_edit_mode   = /bobf/if_conf_c=>sc_edit_read_only
              IMPORTING
                et_data        = lt_stop_data
                eo_message     = lo_message ).

            IF lt_stop_data IS NOT INITIAL.
              lt_stop_data_temp = CORRESPONDING #( lt_stop_data ).
              SORT lt_stop_data_temp BY stop_seq_pos.
              READ TABLE lt_stop_data_temp WITH KEY stop_seq_pos = lc_l
              ASSIGNING FIELD-SYMBOL(<lfs_stop_data>) BINARY SEARCH.
              IF sy-subrc IS INITIAL.
                DATA(lv_ship_timestamp) = <lfs_stop_data>-plan_trans_time.
              ENDIF.
              IF lv_ship_timestamp IS NOT INITIAL.
                lv_temp_date = lv_ship_timestamp.
                lv_ship_date = lv_temp_date+4(2) && |/| && lv_temp_date+6(2) && |/| && lv_temp_date+0(4).
              ENDIF.
            ENDIF.
          CATCH /bobf/cx_frw_contrct_violation.
        ENDTRY.

*--Ship to Address
        IF lv_consignee_id IS NOT INITIAL.
          SELECT addressid
          FROM zi_us_tm_apo_location
          WHERE location  = @lv_consignee_id
          ORDER BY PRIMARY KEY
          INTO @DATA(lv_adrs_no) UP TO 1 ROWS.
          ENDSELECT.
          IF sy-subrc IS INITIAL.
            SELECT SINGLE addressid,cityname,postalcode,streetname,housenumber,country,region,addresseename1
            FROM i_addrorgnamepostaladdress WITH PRIVILEGED ACCESS
            WHERE addressid = @lv_adrs_no
            INTO @DATA(ls_shipto_addrs).
            IF sy-subrc IS NOT INITIAL.
              CLEAR: ls_shipto_addrs.
            ENDIF.
          ENDIF.
        ENDIF.

        TRY.
*--Item Details
            lo_srv_mgr->retrieve_by_association(
              EXPORTING
                iv_node_key    = /scmtms/if_tor_c=>sc_node-root
                it_key         = lt_key
                iv_association = /scmtms/if_tor_c=>sc_association-root-item_tr
                iv_fill_data   = abap_true
                iv_edit_mode   = /bobf/if_conf_c=>sc_edit_read_only
              IMPORTING
                et_data        = lt_tor_item
                eo_message     = lo_message ).

            IF lt_tor_item IS NOT INITIAL.
              lt_tor_item_temp = CORRESPONDING #( lt_tor_item ).
              SORT lt_tor_item_temp BY item_cat main_cargo_item.

              IF lt_tor_item_temp IS NOT INITIAL.
                READ TABLE lt_tor_item_temp WITH KEY item_cat = lc_prd main_cargo_item = abap_true
                ASSIGNING FIELD-SYMBOL(<lfs_tor_item_temp>) BINARY SEARCH.
                IF sy-subrc IS INITIAL.
                  DATA(lv_plant) = <lfs_tor_item_temp>-loading_point_id.
                ENDIF.
              ENDIF.
            ENDIF.
          CATCH /bobf/cx_frw_contrct_violation.
        ENDTRY.

        TRY.
*--Sold to Party
            lo_srv_mgr->retrieve_by_association(
              EXPORTING
                iv_node_key    = /scmtms/if_tor_c=>sc_node-root
                it_key         = lt_key
                iv_association = /scmtms/if_tor_c=>sc_association-root-party
                iv_fill_data   = abap_true
                iv_edit_mode   = /bobf/if_conf_c=>sc_edit_read_only
              IMPORTING
                et_data        = lt_soldtoparty
                eo_message     = lo_message ).

            IF lt_soldtoparty IS NOT INITIAL.
              lt_soldtoparty_temp = CORRESPONDING #( lt_soldtoparty ).
              SORT lt_soldtoparty_temp BY party_rco.
              READ TABLE lt_soldtoparty_temp WITH KEY party_rco = lc_sp
              ASSIGNING FIELD-SYMBOL(<lfs_soldtoparty>) BINARY SEARCH.
              IF sy-subrc IS INITIAL.
                DATA(lv_soldtoparty) = <lfs_soldtoparty>-party_id.
              ENDIF.
            ENDIF.
          CATCH /bobf/cx_frw_contrct_violation.
        ENDTRY.

*--Customer Email Address
        IF lv_soldtoparty IS NOT INITIAL.
          SELECT b~emailaddress
          FROM i_buspartaddress WITH PRIVILEGED ACCESS AS a
          INNER JOIN i_addressemailaddress_2 WITH PRIVILEGED ACCESS AS b
          ON b~addressid = a~addressid
          WHERE a~businesspartner = @lv_soldtoparty
          INTO TABLE @DATA(lt_customer_email).
        ENDIF.

*--Account Detail
        SELECT SINGLE b~addresseename1 FROM i_buspartaddress WITH PRIVILEGED ACCESS AS a
        INNER JOIN i_addrorgnamepostaladdress AS b ON b~addressid = a~addressid
        WHERE a~businesspartner = @lv_consignee_id
        INTO @DATA(lv_account).


        IF lv_purch_org = lc_comp1.  "'50000207'.
*--company1 Logo from se78.
          CALL METHOD cl_ssf_xsf_utilities=>get_bds_graphic_as_bmp
            EXPORTING
              p_object       = lc_graphics
              p_name         = lc_company1
              p_id           = lc_bmap
              p_btype        = lc_bcol
            RECEIVING
              p_bmp          = lv_hama_logo
            EXCEPTIONS
              not_found      = 1
              internal_error = 2
              OTHERS         = 3.
          IF sy-subrc IS INITIAL.
            DATA(lv_logo_xstring) = lv_hama_logo.
          ENDIF.

        ELSEIF lv_purch_org = lc_comp2.  "'50000201'.
*--company2 Logo from se78.
          CALL METHOD cl_ssf_xsf_utilities=>get_bds_graphic_as_bmp
            EXPORTING
              p_object       = lc_graphics
              p_name         = lc_company2
              p_id           = lc_bmap
              p_btype        = lc_bcol
            RECEIVING
              p_bmp          = lv_ener_logo
            EXCEPTIONS
              not_found      = 1
              internal_error = 2
              OTHERS         = 3.
          IF sy-subrc IS INITIAL.
            lv_logo_xstring = lv_ener_logo.
          ENDIF.
        ENDIF.

*--Fetch Sender's Email Id.
        APPEND INITIAL LINE TO lr_name ASSIGNING FIELD-SYMBOL(<lfs_name>).
        <lfs_name>-sign   = cl_abap_range=>sign-including.
        <lfs_name>-option = cl_abap_range=>option-equal.
        <lfs_name>-low    = lc_name1.

        APPEND INITIAL LINE TO lr_name ASSIGNING <lfs_name>.
        <lfs_name>-sign   = cl_abap_range=>sign-including.
        <lfs_name>-option = cl_abap_range=>option-equal.
        <lfs_name>-low    = lc_name2.

        SELECT changeid,name,low FROM zi_tvarvctableforcusto
        WHERE changeid = @lc_us_tm004
        AND name IN @lr_name ORDER BY PRIMARY KEY
        INTO TABLE @DATA(lt_tvarvc).

        IF sy-subrc IS INITIAL.
          IF lv_purch_org = lc_comp1.
            READ TABLE lt_tvarvc WITH KEY name = lc_name1 ASSIGNING FIELD-SYMBOL(<lfs_tvarvc>) BINARY SEARCH.
            IF sy-subrc IS INITIAL.
              DATA(lv_sender_email) = <lfs_tvarvc>-low.
            ENDIF.
          ELSEIF lv_purch_org = lc_comp2.
            READ TABLE lt_tvarvc WITH KEY name = lc_name2 ASSIGNING <lfs_tvarvc> BINARY SEARCH.
            IF sy-subrc IS INITIAL.
              lv_sender_email = <lfs_tvarvc>-low.
            ENDIF.
          ENDIF.
        ENDIF.

        IF lv_sender_email IS INITIAL.
          lv_msg = |Sender Email not maintained in Table: ZI_TVARVCTABLEFORCUSTO - Return|.
          log_free_text if_bali_constants=>c_severity_error lv_msg.
          rp_status = 2.
          save_log_and_return.
        ENDIF.

**************************************************************************
*--EMAIL SENDING LOGIC
**************************************************************************
        IF lt_customer_email IS NOT INITIAL.
          TRY.
              DATA(lo_mail) = cl_bcs_mail_message=>create_instance( ).

              lo_mail->set_sender( CONV #( lv_sender_email ) ).

              LOOP AT lt_customer_email ASSIGNING FIELD-SYMBOL(<lfs_cust_emails>).
                lo_mail->add_recipient( CONV #( <lfs_cust_emails>-emailaddress ) ).
              ENDLOOP.

              lo_mail->set_subject( TEXT-001 ).

*--Add Logo to Body of Email.
              lv_company_logo = 'Company Logo'(002).
              lo_mail->add_attachment( cl_bcs_mail_binarypart=>create_instance(
                                         iv_content      = lv_logo_xstring
                                         iv_content_type = lc_type      "'image/bmp'
                                         iv_filename     = lv_company_logo ) ).

              lv_html =
                |<html>| &&
                 |<body style="font-family: Arial, sans-serif;">| &&
                  |<div style="text-align:left;">| &&
                  |<img src="cid:{ lv_company_logo }" width="1000" height="150" alt="Company Logo" /> <br>| &&
                  |</div>| &&
                |<hr/>| &&
                 |<p><b>Your company1 order has been shipped - PO# { lv_po_no } on { lv_ship_date }.</b></p>| &&
                 |<p>Thank you for your recent order. The items on your order have been shipped. See below for details.</p><br> | &&

                |<table cellpadding="5" style="border-collapse: collapse; width: 80%;">| &&
                 |<tr><th style="border: none; text-align: left;"><b>Order Details</b></th>| &&
                 |<th style="border: none; text-align: left;"><b>Shipping Address</b></th></tr>| &&

*--Tags for Order Details & Shipping Address
                |<tr><td style="border: none;">Order no: { |{ lv_sales_order ALPHA = OUT }| }</td>| &&
                |<td style="border: none;">{ ls_shipto_addrs-addresseename1 }</td></tr>| &&

                |<tr><td style="border: none;">Shipping Method: { ls_delv_det-shippingcondition } - { ls_delv_det-shippingconditionname }</td>| &&
                |<td style="border: none;">{ ls_shipto_addrs-housenumber },{ ls_shipto_addrs-streetname }</td></tr>| &&

                |<tr><td style="border: none;">Ship Date: { lv_ship_date }</td>| &&
                |<td style="border: none;">{ ls_shipto_addrs-cityname },{ ls_shipto_addrs-region },| &&
                |{ ls_shipto_addrs-postalcode }</td></tr>| &&

                |<tr><td style="border: none;">Tracking no: { lv_tracking_no }</td>| &&
                |<td style="border: none;">{ ls_shipto_addrs-country }</td></tr></table><br>| &&

*--Dark Lines
             |<hr style="margin-bottom: 0.6cm; border: 1px solid black;"/>| &&
             |<hr style="border: 1px solid black;"/>| &&
*--Populate Item Details
                |<table cellpadding="5" style="border-collapse: collapse; width: 80%;">| &&
                  |<tr>| &&
                    |<th style="border: none; text-align: left;"><b>Item Number</b></th>| &&
                    |<th style="border: none; text-align: left;"><b>Material Number</b></th>| &&
                    |<th style="border: none; text-align: left;"><b>Description</b></th>| &&
                    |<th style="border: none; text-align: left;"><b>Order Quantity</b></th>| &&
                  |</tr>|.

              LOOP AT lt_tor_item ASSIGNING FIELD-SYMBOL(<lfs_item>).
                IF <lfs_item>-item_cat = lc_prd AND <lfs_item>-main_cargo_item = abap_true.
                  lv_qty = <lfs_item>-qua_pcs_val.
                  lv_html_item = lv_html_item &&
                      |<tr>| &&
                         |<td style="border: none;">{ |{ <lfs_item>-item_id ALPHA = OUT }| }</td>| &&
                         |<td style="border: none;">{ |{ <lfs_item>-product_id ALPHA = OUT }| }</td>| &&
                         |<td style="border: none;">{ <lfs_item>-item_descr }</td>| &&
                         |<td style="border: none;">{ lv_qty }</td>| &&
                       |</tr>|.
                  CLEAR: lv_qty.
                ENDIF.
              ENDLOOP.

              IF lv_html_item IS NOT INITIAL.
                lv_html = lv_html && lv_html_item.
              ENDIF.

*--Dark Lines
              lv_html = lv_html && |</table>| && |<hr style="margin-bottom: 0.6cm; border: 1px solid black;"/>| &&
              |<hr style="border: 1px solid black;"/>| &&

              |<b>Tracking URL</b><br>| &&
              |<a href="{ lv_tracking_url }" style="color: #87CEEB; text-decoration: underline;" target="_blank">{ lv_tracking_url }</a>| &&
              |<br/>| &&
              |</body></html>|.


              LOOP AT lt_atf_file ASSIGNING FIELD-SYMBOL(<lfs_atf_file>).
                IF <lfs_atf_file>-content IS NOT INITIAL.
                  lo_mail->add_attachment(
                    cl_bcs_mail_binarypart=>create_instance(
                      iv_content      = <lfs_atf_file>-content
                      iv_content_type = lc_mimetype               "'application/pdf'
                      iv_filename     = CONV #( <lfs_atf_file>-file_name )
                    )
                  ).
                ENDIF.
              ENDLOOP.

              lo_mail->set_main( cl_bcs_mail_textpart=>create_text_html( lv_html ) ).

              lo_mail->send( IMPORTING ev_mail_status = DATA(lv_status) ).

              IF lv_status = 'E'.
                lv_msg = |Email Sending Failed - Return|.
                log_free_text if_bali_constants=>c_severity_error lv_msg.
                rp_status = 2.
                save_log_and_return.
              ELSE.
                lv_msg = |Email Sent Successfully|.
                log_free_text if_bali_constants=>c_severity_status lv_msg.
                rp_status = 1.
                save_log_and_return.
              ENDIF.

            CATCH cx_bcs_mail INTO DATA(lx_mail).
          ENDTRY.
        ELSE.
          lv_msg = |Customer Email not maintained in Customer Master - Return|.
          log_free_text if_bali_constants=>c_severity_error lv_msg.
          rp_status = 2.
          save_log_and_return.
        ENDIF.

      WHEN lc_hazard_form.  "ZTM_TOR_HAZARD_FORM.
        rp_status = 1.
      WHEN OTHERS.
    ENDCASE.

  ENDMETHOD.

 

2 Comments
Labels in this area