Интеграция со СБИС

Формирование xml-документов с помощью программ печати

Формирование xml-документов с помощью программ печати

СБИС САПЕР использует имеющиеся программы печати для формирование xml-документов. Это позволяет избежать дублирования алгоритма формирования документа.

Алгоритм формирования электронного документа

  1. Для каждого отправляемого документа СБИС САПЕР вызывает программу печати, которая указана в настройках модуля.
  2. Программа печати рассчитывает данные, которые нужны для печати.
  3. Перед вызовом формуляра, управление передается модулю СБИС САПЕР. Модуль проверяет, кем была вызвана программу печати. Если инициатор вызова:
    • не САПЕР — модуль возвращает управление программе печати.
    • САПЕР — выбирает подготовленные программой печати данные. Выбор нужных для печати данных определяется по настройкам выгрузки. Затем формируется xml-документ. По окончании процесса , модуль возвращает флаг, который говорит о необходимости прервать программу печати.

Этот алгоритм работает на любыми версиями SAP, типами документов и отчетов (не зависит от функционала, реализованного SAP для журнала электронных счетов фактур из российского Add-on).

Доработка программ печати

Перед тем как вносить изменения в программу печати, обязательно сделайте ее копию. Рекомендуемый шаблон названия копии программы «[ZSBIS_][Старое название программы]». Вместо копий программ печати можно использовать стандартные BADI в программах печати. Например, «J_3R_TORG12_BADI» для программы печати накладной «J_3RV_DELIV_PDF» или «J_3R_INV_BADI» для программы печати фактуры «J_3RV_INV_A».

В программу печати или ее копию добавьте вызов метода СБИС САПЕР. Метод должен завершать действия программы печати после формирования электронного документа.

Стандартные программы печати
Вызов из BADI
Вызов из формуляра SMARTFORM
Вызов из формуляра PDF

Пример кода, который нужно добавить перед вызовом формуляра в каждую программу печати:

TRY.
      DATA CX_ROOT TYPE REF TO CX_ROOT.
      DATA lv_not_print TYPE c VALUE ''.
      DATA cl_mapping TYPE REF TO /sbis/cl_mapping.
      CREATE OBJECT cl_mapping.
      CALL METHOD cl_mapping->calc_doc
        EXPORTING
          is_nast      = nast
        IMPORTING
          ev_not_print = lv_not_print.
      IF lv_not_print = 'X'.
        EXIT.
      ENDIF.
 
      DATA cx_core TYPE REF TO /sbis/cx_core.
      CATCH /sbis/cx_core INTO cx_core.
        DATA  lv_cur_prog  TYPE char255.
        DATA  lv_cur_form  TYPE char255.
        CALL METHOD /sbis/cl_core=>get_current_progname
          IMPORTING
            ev_prog_name = lv_cur_prog
            ev_form_name = lv_cur_form.
        FIELD-SYMBOLS: <fs_exc> TYPE /sbis/s_cx_core.
        ASSIGN ('(/SBIS/SAPLGF_PRINT_PROG)GS_EXC') TO <fs_exc>.
        IF  <fs_exc>    IS ASSIGNED.
          <fs_exc>-error_msg_ext    = cx_core->lv_error_msg_ext.
          <fs_exc>-error_msg_detail = cx_core->lv_error_msg_detail
                  && ` <= ` && lv_cur_prog && `->` && lv_cur_form.
        ENDIF.
        RAISE EXCEPTION TYPE /sbis/cx_core
          EXPORTING
            textid              = cx_core->textid
            lv_error_msg_ext    = cx_core->lv_error_msg_ext
            lv_error_msg_detail = cx_core->lv_error_msg_detail
            && ` <= ` && lv_cur_prog && `->` && lv_cur_form.
    ENDTRY.

Если в формулярах печатных форм есть логика расчета данных документа — перенесите ее в программу печати.

Если у вас Z-программы печати используют подпрограммы, то для вызова СБИС САПЕР:

  • Сначала запускается подпрограмма «ENTRY». Это оболочка для подпрограммы «PROCESSING». Она передает код возврата, в ней изменения не понадобятся.
    FORM entry USING return_code us_screen.                     "#EC CALLED
      CLEAR retcode.
      xscreen = us_screen.
      PERFORM processing USING us_screen.
      IF retcode NE 0.
        return_code = 1.
      ELSE.
        return_code = 0.
      ENDIF.
      CLEAR status.
    ENDFORM.
    
  • Вызов печати обычно находится в теле подпрограммы «PROCESSING».
    FORM processing USING proc_screen.
      PERFORM checks.
      PERFORM init_data.
      PERFORM get_data.
      PERFORM print.
    ENDFORM.
    
  • Поэтому до вызова печати («PRINT») нужно вставить СБИС-код формирования электронных документов.
    DATA  gv_not_print TYPE c .        " TENSOR SBIS EDO
     
    FORM processing USING proc_screen.
     
      PERFORM checks.
      PERFORM init_data.
      PERFORM get_data.
      PERFORM sbis_edi.                " TENSOR SBIS EDO
      CHECK gv_not_print IS INITIAL.   " TENSOR SBIS EDO
      PERFORM print.
     
    ENDFORM.
     
    FORM sbis_edi .
    * TENSOR SBIS EDO
      TRY.
          DATA CX_ROOT TYPE REF TO CX_ROOT.
          DATA cl_mapping TYPE REF TO /sbis/cl_mapping.
          CREATE OBJECT cl_mapping.
          CALL METHOD cl_mapping->calc_doc
            EXPORTING
              is_nast      = nast
            IMPORTING
              ev_not_print = gv_not_print.
     
          DATA cx_core TYPE REF TO /sbis/cx_core.
          CATCH /sbis/cx_core INTO cx_core.
            DATA  lv_cur_prog  TYPE char255.
            DATA  lv_cur_form  TYPE char255.
            CALL METHOD /sbis/cl_core=>get_current_progname
              IMPORTING
                ev_prog_name = lv_cur_prog
                ev_form_name = lv_cur_form.
            " exception проходит через прогр печати без текста!
            FIELD-SYMBOLS: <fs_exc> TYPE /sbis/s_cx_core.
            ASSIGN ('(/SBIS/SAPLGF_PRINT_PROG)GS_EXC') TO <fs_exc>.
            IF  <fs_exc>    IS ASSIGNED.
              <fs_exc>-error_msg_ext    = cx_core->lv_error_msg_ext.
              <fs_exc>-error_msg_detail = cx_core->lv_error_msg_detail
                                        && ` <= ` && lv_cur_prog && `->` && lv_cur_form.
            ENDIF.
            RAISE EXCEPTION TYPE /sbis/cx_core
              EXPORTING
                textid              = cx_core->textid
                lv_error_msg_ext    = cx_core->lv_error_msg_ext
                lv_error_msg_detail = cx_core->lv_error_msg_detail
                                      && ` <= ` && lv_cur_prog && `->` && lv_cur_form.
      ENDTRY.
    ENDFORM.
    

В зависимости от флага «gv_not_print» происходит либо печать, либо выход из программы с правильным кодом возврата.

В СБИС САПЕР имеются реализации стандартных BADI и точек расширения для программ печати:

  • класс «/SBIS/CL_J_3R_INV_BADI» — для печати накладных;
  • класс «/SBIS/CL_J3R_TORG12_BADI» — для печати фактур;
  • точка расширения «/SBIS/ENHI_J_3RV_TORG12_BIL» — для печати актов.

Проверьте, что активированы BADI «J_3R_TORG12_BADI», «J_3R_INV_BADI» и точка расширения «ESJ_3RV_FORM_UPDATE». Используейте готовые решения, реализованные в данных классах.

Если BADI активированы, установлен статус «Внедрение вызывается».

Пример вызова из BADI для программы печати накладной ТОРГ-12:

METHOD j_3r_torg12_badi_interface~doc_details.
 
** I_VBDKL    TYPE VBDKL
** T_VBDPL    TYPE EHS_VBDPL_T
** EDITABLE   TYPE XFELD
** HDOC       TYPE J_3RV_HT12
** ITEMS      TYPE J_3RV_TT12
 
**************************************************************
*                 TENSOR SBIS EDO                            *
**************************************************************
    DATA lv_prog_and_field TYPE char255.
    TRY.
*" GET NAST
        "имя программы берем из инишки сверху
        FIELD-SYMBOLS: <lfs_prog_name> TYPE char40.
        ASSIGN ('(/SBIS/SAPLGF_PRINT_PROG)GV_PROG_NAME') TO <lfs_prog_name>.
        IF <lfs_prog_name> IS ASSIGNED.
 
          lv_prog_and_field = `(` && <lfs_prog_name> && `)` && 'NAST'.
          FIELD-SYMBOLS: <lfs_nast> TYPE nast.
*          ASSIGN ('(J_3RV_DELIV_PDF)NAST') TO <lfs_nast>.
          ASSIGN (lv_prog_and_field) TO <lfs_nast>.
          IF <lfs_nast> IS ASSIGNED.
*" MAPPING
            DATA CX_ROOT TYPE REF TO CX_ROOT.
            DATA cl_mapping TYPE REF TO /sbis/cl_mapping.
            CREATE OBJECT cl_mapping.
            CALL METHOD cl_mapping->calc_doc
              EXPORTING
                is_nast      = <lfs_nast>
              IMPORTING
                ev_not_print = gv_not_print.
          ELSE.
            "нет такой переменной - исключение!
            RAISE EXCEPTION TYPE /sbis/cx_core
              EXPORTING
                textid              = /sbis/cx_core=>/sbis/cx_core
                lv_error_msg_ext    = `Variable not assigned: '`
                                      && lv_prog_and_field && `'`
                lv_error_msg_detail = ''.
          ENDIF. " IF <lfs_nast> IS ASSIGNED.
 
*" EXIT FROM PRINT PROGRAM
          IF NOT gv_not_print IS INITIAL.
            lv_prog_and_field = `(` && <lfs_prog_name> && `)` && 'VBDKL'.
            FIELD-SYMBOLS: <lfs_vbdkl> TYPE vbdkl.
            "ASSIGN ('(J_3RV_DELIV_PDF)VBDKL') TO <lfs_vbdkl>.
            ASSIGN (lv_prog_and_field) TO <lfs_vbdkl>.
            IF <lfs_vbdkl> IS ASSIGNED.
              CLEAR <lfs_vbdkl>-vbeln. " хитрый способ выйти из прогр J_3RV_DELIV_PDF
            ELSE.
              "если в логике программы что-то поменялось - исключение!
              RAISE EXCEPTION TYPE /sbis/cx_core
                EXPORTING
                  textid              = /sbis/cx_core=>/sbis/cx_core
                  lv_error_msg_ext    = `Variable not assigned: '`
                                        && lv_prog_and_field && `'`
                  lv_error_msg_detail = ''.
            ENDIF. " IF <lfs_vbdkl> IS ASSIGNED.
          ENDIF.
        ENDIF. " IF <lfs_prog_name> IS ASSIGNED.
 
      CATCH /sbis/cx_core INTO cx_core.
        DATA  lv_cur_prog  TYPE char255.
        DATA  lv_cur_form  TYPE char255.
        CALL METHOD /sbis/cl_core=>get_current_progname
          IMPORTING
            ev_prog_name = lv_cur_prog
            ev_form_name = lv_cur_form.
        " exception проходит через прогр печати без текста!
        FIELD-SYMBOLS: <fs_exc> TYPE /sbis/s_cx_core.
        ASSIGN ('(/SBIS/SAPLGF_PRINT_PROG)GS_EXC') TO <fs_exc>.
        IF  <fs_exc>    IS ASSIGNED.
          <fs_exc>-error_msg_ext    = cx_core->lv_error_msg_ext.
          <fs_exc>-error_msg_detail = cx_core->lv_error_msg_detail
                                    && ` <= ` && lv_cur_prog && `->` && lv_cur_form.
        ENDIF.
        RAISE EXCEPTION TYPE /sbis/cx_core
          EXPORTING
            textid              = cx_core->textid
            lv_error_msg_ext    = cx_core->lv_error_msg_ext
            lv_error_msg_detail = cx_core->lv_error_msg_detail
                                    && ` <= ` && lv_cur_prog && `->` && lv_cur_form.
    ENDTRY.
  ENDMETHOD.

В зависимости от флага «gv_not_print» происходит либо печать, либо выход из BADI и из программы печати.

Вызов из формуляра нужен, когда в системе нет отдельной программы печати или когда значительная часть логики перенесена в формуляр.

Особенности вызова

  • Из программы печати вызывается формуляр. Из него нужно вызвать код СБИС, затем выйти из формуляра, а после — из программы.
  • Передаваемые в САПЕР данные формуляра должны быть объявлены глобально.
  • Вызов кода СБИС нужно вставлять в элемент смартформы «строки программы» — там есть доступ к подготовленным данным печати. Например, в основной цикл по позициям.
  • Не нужно вставлять код СБИС в инициализацию. В ней у СБИС САПЕР нет доступа к глобальным переменным формуляра через assign. Также в инициализации не обеспечивается корректный выход из формуляра «/ФМ» со значением «rc=0».

Пример кода СБИС:

* TENSOR SBIS EDO
TRY.
    DATA CX_ROOT TYPE REF TO CX_ROOT.
    DATA lv_not_print TYPE c VALUE ''.
    DATA cl_mapping TYPE REF TO /sbis/cl_mapping.
    CREATE OBJECT cl_mapping.
    CALL METHOD cl_mapping->calc_doc_efg
      EXPORTING
        iv_ini_name  = 'ZSF_INVOICE'
      IMPORTING
        ev_not_print = lv_not_print.
    IF lv_not_print = 'X'.
      " надо выйти без печати!
      " Set error message
      CALL FUNCTION 'SSFRT_WRITE_ERROR'
        EXPORTING
          i_msgid = '00'
          i_msgno = '208'
          i_msgv1 = 'SBIS: not print'.
* Raise the excption
      user_exception user_canceled.
    ENDIF.
 
  CATCH /sbis/cx_core INTO cx_core.
    " надо выйти без печати!
    " SET error message
    CALL FUNCTION 'SSFRT_WRITE_ERROR'
      EXPORTING
*       I_ERRNUMBER =
        i_msgid = '00'
*       I_MSGTY = 'E'
        i_msgno = '208'
        i_msgv1 = 'SBIS: not print'.
* Raise the excption
    user_exception user_canceled.
 
  CATCH CX_ROOT INTO CX_ROOT.
    " надо выйти без печати!
    " SET error message
    CALL FUNCTION 'SSFRT_WRITE_ERROR'
      EXPORTING
*       I_ERRNUMBER =
        i_msgid = '00'
*       I_MSGTY = 'E'
        i_msgno = '208'
        i_msgv1 = 'SBIS: not print'.
* Raise the excption
    user_exception user_canceled.
ENDTRY.

Как правило, программа печати не требует изменений и сама формирует код возврата.

Вызов из формуляра нужен, когда в системе нет отдельной программы печати или когда значительная часть логики перенесена в формуляр.

Особенности вызова

  • Из программы печати вызывается формуляр. Из него нужно вызвать код СБИС, затем выйти из формуляра, а после — из программы.
  • Вызов кода СБИС нужно вставлять в интерфейсе формуляра в код инициализации или в подпрограмму — там есть доступ к подготовленным данным печати.

Пример кода СБИС:

**************************************************************
*                 TENSOR SBIS EDO                            *
**************************************************************
  TRY.
      DATA CX_ROOT TYPE REF TO CX_ROOT.
      DATA lv_not_print TYPE c VALUE ''.
      DATA cl_mapping TYPE REF TO /sbis/cl_mapping.
      CREATE OBJECT cl_mapping.
      CALL METHOD cl_mapping->calc_doc
        EXPORTING
          iv_ini_name = 'DP_TOVTORGPR_1175010'  " 
        IMPORTING
          ev_not_print = lv_not_print.
      IF lv_not_print = 'X'.
        RETURN.
        MESSAGE ID 'SU' TYPE '-' NUMBER 000 WITH 'SBIS_COMPLETE'
          RAISING usage_error.
      ENDIF.
    CATCH CX_ROOT INTO CX_ROOT.
  ENDTRY.

В программе печати нужно предусмотреть корректный выход с правильным кодом возврата.

Пример:

CALL FUNCTION func_module_name
        EXPORTING
          /1bcdwb/docparams  = fp_docparams
          h_item             = items
          h_header           = h_doc
        IMPORTING
          /1bcdwb/formoutput = ls_formoutput
        EXCEPTIONS
          usage_error        = 1
          system_error       = 2
          internal_error     = 3.
 
**************************************************************
*                 TENSOR SBIS EDO - BEGIN                    *
**************************************************************
      IF sy-subrc <> 0 AND sy-msgv1 = 'SBIS_COMPLETE'.
        sy-subrc = 0.
        CALL FUNCTION 'FPCOMP_FORM_END'
          EXCEPTIONS
            usage_error    = 1
            system_error   = 2
            internal_error = 3
            OTHERS         = 4.
      ELSEIF sy-subrc <> 0.
**************************************************************
*                 TENSOR SBIS EDO - END                      *
**************************************************************
        retcode = sy-subrc.
        PERFORM protocol_update.
        MESSAGE e073 INTO gv_dummy.
        PERFORM protocol_update.
      ENDIF.

Возможные доработки программ печати

  • В программе печати данные, которые нужны для корректного формирования xml, должны храниться в отдельных полях. Например, в программе печати данные о контрагенте (наименование, ИНН/КПП) содержатся в одном поле, а в печатной форме документа — в отдельных строках.