пятница, 21 июля 2017 г.

SAP GUI 7.50 + Patch Level 1

SAP GUI 7.50
SAP GUI 7.50

Patch Level 1
Patch Level 1

пятница, 3 марта 2017 г.

Когда вызывается ФМ, если он IN BACKGROUND TASK?

Вызывается он после завершения UPDATE процессов (CAL FUNCTION ... IN UPDATE TASK). И вот доказательство.
Создаем вот такую табличку:


Создаем вот такой ФМ типа RFC:
FUNCTION zfm_krs_test_bg.
*"--------------------------------------------------------------------
*"*"Локальный интерфейс:
*"  IMPORTING
*"     VALUE(ID) TYPE  CHAR10
*"--------------------------------------------------------------------
  DATA ls_data TYPE zkrs_test_bgto.

  ls_data-id = id.

  GET TIME STAMP FIELD ls_data-tst.

  MODIFY zkrs_test_bgto FROM ls_data.
  COMMIT WORK.

ENDFUNCTION.

Еще один типа UPDATE TASK немедленного запуска (обратите внимание что в нем еще раз запускается BG-ФМ со своим ID):
FUNCTION zfm_krs_test_upd.
*"----------------------------------------------------------------------
*"*"Функциональный модуль обновления:
*"
*"*"Локальный интерфейс:
*"  IMPORTING
*"     VALUE(ID) TYPE  CHAR10
*"     VALUE(IV_WAIT) TYPE  INT4 DEFAULT 5
*"----------------------------------------------------------------------
  DATA ls_data TYPE zkrs_test_bgto.

  ls_data-id = id.

  WAIT UP TO iv_wait SECONDS.

  GET TIME STAMP FIELD ls_data-tst.


  MODIFY zkrs_test_bgto FROM ls_data.

  ls_data-id = |BG{ id }|.

  CALL FUNCTION 'ZFM_KRS_TEST_BG'
    IN BACKGROUND TASK
    EXPORTING
      id = ls_data-id.

ENDFUNCTION.

И еще один UPDATE TASK отложенного запуска:
FUNCTION zfm_krs_test_upd2.
*"----------------------------------------------------------------------
*"*"Функциональный модуль обновления:
*"
*"*"Локальный интерфейс:
*"  IMPORTING
*"     VALUE(ID) TYPE  CHAR10
*"----------------------------------------------------------------------
  DATA ls_data TYPE zkrs_test_bgto.

  ls_data-id = id.

*  WAIT UP TO 5 SECONDS.

  GET TIME STAMP FIELD ls_data-tst.

  MODIFY zkrs_test_bgto FROM ls_data.

ENDFUNCTION.
Для наглядности где какой тип ставить картинка:

И выполняем вот такой код для проверки
CALL FUNCTION 'ZFM_KRS_TEST_BG'
    IN BACKGROUND TASK
    EXPORTING
      id = 'BG'.

  CALL FUNCTION 'ZFM_KRS_TEST_UPD'
    IN UPDATE TASK
    EXPORTING
      id = 'U0'
      iv_wait = 0.


  CALL FUNCTION 'ZFM_KRS_TEST_UPD'
    IN UPDATE TASK
    EXPORTING
      id = 'U1'
      iv_wait = 5.

  CALL FUNCTION 'ZFM_KRS_TEST_UPD2'
    IN UPDATE TASK
    EXPORTING
      id = 'U2'.

  COMMIT WORK.
Как видите, тут мы вначале регистрируем BG-ФМ, потом UPD-ФМ с нулевой задержкой внутри, потом UPD-ФМ с задержкой в 5 секунд перед обновлением и завершением, и, наконец, UPD-ФМ с задержкой обновления.
Наша задача доказать что BG-ФМ выполнится последним, несмотря на то, что зарегистрирован первым, и главное выполнится только после всех UPD-ФМ. И заодно проверим вызовется ли BG-ФМ из UPD-ФМ без COMMIT.
Запускаем и смотрим в таблицу (таблица для наглядности отсортирована по времени выполнения):


Итак, какие можно сделать выводы.
  1. BG-ФМ запускается после выполнения всех UPD-ФМ (даже после UPD-ФМ с задержкой запуска) 
  2. BG-ФМ, вызванный из UPD-ФМ, не нуждается в дополнительном COMMIT для запуска 
  3. BG-ФМ, вызванный из UPD-ФМ, также запускается только после выполнения всех UPD-ФМ (даже после UPD-ФМ с задержкой запуска) 
  4. BG-ФМ, зарегистрированный до COMMIT, вызывается позже чем BG-ФМ, вызванные из UPD-ФМ

ЧТД.

пятница, 16 декабря 2016 г.

Вызываем FBLN1 с неколькими BELNR, BUKRS, LIFNR через пакетник

CLASS zcl_call_fbl1n DEFINITION
PUBLIC
ABSTRACT
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
TYPES:
tt_bukrs TYPE STANDARD TABLE OF bukrs WITH DEFAULT KEY .
TYPES:
tt_belnr TYPE STANDARD TABLE OF belnr_d WITH DEFAULT KEY .
TYPES:
tt_gjahr TYPE STANDARD TABLE OF gjahr WITH DEFAULT KEY .
TYPES:
tt_lifnr TYPE STANDARD TABLE OF lifnr WITH DEFAULT KEY .
CLASS-DATA st_bdc TYPE bdcdata_tab READ-ONLY .
CLASS-METHODS call
IMPORTING
!it_bukrs TYPE tt_bukrs OPTIONAL
!it_belnr TYPE tt_belnr OPTIONAL
!it_gjahr TYPE tt_gjahr OPTIONAL
!it_lifnr TYPE tt_lifnr OPTIONAL
VALUE(is_ctu_params) TYPE ctu_params OPTIONAL
EXPORTING
!et_msg TYPE tab_bdcmsgcoll .
CLASS-METHODS fill_bdc
IMPORTING
!it_bukrs TYPE tt_bukrs OPTIONAL
!it_belnr TYPE tt_belnr OPTIONAL
!it_gjahr TYPE tt_gjahr OPTIONAL
!it_lifnr TYPE tt_lifnr OPTIONAL .
protected section.
private section.
class-methods _SCREEN
importing
!IV_VALUE type CLIKE .
class-methods _FIELD
importing
!IV_VALUE type CLIKE .
class-methods _SELOPT
importing
!IT_DATA type STANDARD TABLE .
ENDCLASS.
CLASS ZCL_call_FBL1N IMPLEMENTATION.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_call_FBL1N=>CALL
* +-------------------------------------------------------------------------------------------------+
* | [--->] IT_BUKRS TYPE TT_BUKRS(optional)
* | [--->] IT_BELNR TYPE TT_BELNR(optional)
* | [--->] IT_GJAHR TYPE TT_GJAHR(optional)
* | [--->] IT_LIFNR TYPE TT_LIFNR(optional)
* | [--->] IS_CTU_PARAMS TYPE CTU_PARAMS(optional)
* | [<---] ET_MSG TYPE TAB_BDCMSGCOLL
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD call.
FREE et_msg.
fill_bdc(
EXPORTING
it_bukrs = it_bukrs " Балансовая единица
it_belnr = it_belnr
it_gjahr = it_gjahr
it_lifnr = it_lifnr
).
IF is_ctu_params-dismode is INITIAL .
is_ctu_params-dismode = 'E'.
ENDIF.
IF is_ctu_params-nobinpt is INITIAL and sy-batch is INITIAL.
is_ctu_params-nobinpt = 'X'.
ENDIF.
CALL TRANSACTION 'FBL1N'
WITH AUTHORITY-CHECK
USING st_bdc
OPTIONS FROM is_ctu_params
MESSAGES INTO et_msg
.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_call_FBL1N=>FILL_BDC
* +-------------------------------------------------------------------------------------------------+
* | [--->] IT_BUKRS TYPE TT_BUKRS(optional)
* | [--->] IT_BELNR TYPE TT_BELNR(optional)
* | [--->] IT_GJAHR TYPE TT_GJAHR(optional)
* | [--->] IT_LIFNR TYPE TT_LIFNR(optional)
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD fill_bdc.
FREE st_bdc.
IF it_lifnr[] IS NOT INITIAL.
_screen('RFITEMAP 1000 X ').
_field('BDC_CURSOR KD_LIFNR-LOW').
_field('BDC_OKCODE =%004').
* _field(' KD_LIFNR-LOW').
* _field(' X_OPSEL X').
* _field(' PA_STIDA 16.12.2016').
* _field(' X_NORM X').
_field(' BDC_SUBSCR SAPLSSEL 2001%_SUBSCREEN_%_SUB%_CONTAINER').
_field(' BDC_SUBSCR SAPLSSEL 2002SUBSCREEN_CONTAINER2').
_selopt( it_lifnr ).
ENDIF.
IF it_bukrs[] IS NOT INITIAL.
_screen('RFITEMAP 1000 X').
_field(' BDC_CURSOR KD_LIFNR-LOW').
_field(' BDC_OKCODE =%005').
* _field(' KD_LIFNR-LOW 1').
* _field(' X_OPSEL X').
* _field(' PA_STIDA 16.12.2016').
* _field(' X_NORM X').
_field(' BDC_SUBSCR SAPLSSEL 2001%_SUBSCREEN_%_SUB%_CONTAINER').
_field(' BDC_SUBSCR SAPLSSEL 2002SUBSCREEN_CONTAINER2').
_selopt( it_bukrs ).
ENDIF.
IF it_belnr[] IS NOT INITIAL.
_screen('RFITEMAP 1000 X').
_field(' BDC_CURSOR KD_LIFNR-LOW').
_field(' BDC_OKCODE =DYNS').
* _field(' KD_LIFNR-LOW 1').
* _field(' KD_BUKRS-LOW 2000').
* _field(' X_OPSEL X').
* _field(' PA_STIDA 16.12.2016').
* _field(' X_NORM X').
_field(' BDC_SUBSCR SAPLSSEL 2001%_SUBSCREEN_%_SUB%_CONTAINER').
_field(' BDC_SUBSCR SAPLSSEL 2002SUBSCREEN_CONTAINER2').
_screen('RFITEMAP 1000 X').
_field(' BDC_CURSOR KD_LIFNR-LOW').
_field(' BDC_OKCODE =%02411060000707020').
* _field(' KD_LIFNR-LOW 1').
* _field(' KD_BUKRS-LOW 2000').
* _field(' X_OPSEL X').
* _field(' PA_STIDA 16.12.2016').
* _field(' X_NORM X').
_field(' BDC_SUBSCR SAPLSSEL 2001%_SUBSCREEN_%_SUB%_CONTAINER').
_field(' BDC_SUBSCR SAPLSSEL 2000SUBSCREEN_CONTAINER2').
_field(' BDC_SUBSCR SAPLSSEL 1106SUBSCREEN_CONTAINER').
_selopt( it_belnr ).
ENDIF.
_screen('RFITEMAP 1000 X').
_field(' BDC_OKCODE =ONLI').
_field(' BDC_CURSOR KD_LIFNR-LOW').
_field(' X_OPSEL X').
_field(' X_NORM X').
* _field(' X_SHBV X').
* _field(' X_MERK X').
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_call_FBL1N=>_FIELD
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_VALUE TYPE CLIKE
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD _field.
DATA ls_bdc TYPE bdcdata.
CHECK iv_value IS NOT INITIAL.
DATA(lv_value) = condense( iv_value ).
CHECK lv_value IS NOT INITIAL.
* SPLIT lv_value AT cl_abap_char_utilities=>horizontal_tab INTO ls_bdc-fnam ls_bdc-fval .
* SPLIT lv_value AT space INTO ls_bdc-fnam ls_bdc-fval .
FIND REGEX '^\s*(\S+)\s?(.*)$' IN lv_value SUBMATCHES ls_bdc-fnam ls_bdc-fval.
IF sy-subrc = 0.
CONDENSE ls_bdc-fval.
APPEND ls_bdc TO st_bdc.
ENDIF.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_call_FBL1N=>_SCREEN
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_VALUE TYPE CLIKE
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD _screen.
DATA ls_bdc TYPE bdcdata.
CHECK iv_value IS NOT INITIAL.
* SPLIT iv_value AT cl_abap_char_utilities=>horizontal_tab INTO ls_bdc-program ls_bdc-dynpro ls_bdc-dynbegin.
* SPLIT iv_value AT space INTO ls_bdc-program ls_bdc-dynpro ls_bdc-dynbegin.
FIND REGEX '^\s*(\S+)\s+(\d+)(.*)$' IN iv_value SUBMATCHES ls_bdc-program ls_bdc-dynpro DATA(lv_end).
IF sy-subrc = 0.
ls_bdc-dynbegin = condense( lv_end ).
APPEND ls_bdc TO st_bdc.
ENDIF.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_call_FBL1N=>_SELOPT
* +-------------------------------------------------------------------------------------------------+
* | [--->] IT_DATA TYPE STANDARD TABLE
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD _selopt.
DATA lt_value TYPE STANDARD TABLE OF bdcdata-fval.
DATA lv_value TYPE bdcdata-fval.
DATA lv_index TYPE i.
DATA lv_ok_code TYPE string VALUE 'BDC_OKCODE /00'.
CONSTANTS cv_accept TYPE string VALUE 'BDC_OKCODE =ACPT'.
LOOP AT it_data ASSIGNING FIELD-SYMBOL(<ls_data>).
CHECK <ls_data> IS NOT INITIAL.
write <ls_data> to lv_value.
APPEND lv_value TO lt_value.
ENDLOOP.
CHECK lt_value[] IS NOT INITIAL.
SORT lt_value.
DELETE ADJACENT DUPLICATES FROM lt_value.
IF lines( lt_value ) < 9.
lv_ok_code = cv_accept.
ENDIF.
_screen('SAPLALDB 3000 X').
_field( lv_ok_code ).
_field(' BDC_SUBSCR SAPLALDB 3010SCREEN_HEADER').
_field(' BDC_CURSOR RSCSEL_255-SLOW_I(08)').
LOOP AT lt_value ASSIGNING FIELD-SYMBOL(<v_value>) FROM 1 TO 8.
_field( |RSCSEL_255-SLOW_I({ sy-tabix WIDTH = 2 PAD = '0' ALIGN = right }) { <v_value> }| ).
ENDLOOP.
LOOP AT lt_value FROM 9 TRANSPORTING NO FIELDS WHERE table_line IS NOT INITIAL.
if sy-tabix = lines( lt_value ).
lv_ok_code = cv_accept.
ENDif.
lv_index = sy-tabix - 8.
_screen('SAPLALDB 3000 X').
_field( lv_ok_code ).
_field(' BDC_SUBSCR SAPLALDB 3010SCREEN_HEADER').
_field(' BDC_CURSOR RSCSEL_255-SLOW_I(08)').
DO 8 TIMES.
ADD 1 TO lv_index.
READ TABLE lt_value ASSIGNING <v_value> INDEX lv_index.
_field( |RSCSEL_255-SLOW_I({ sy-index WIDTH = 2 PAD = '0' ALIGN = right }) { <v_value> }| ).
ENDDO.
ENDLOOP.
ENDMETHOD.
ENDCLASS.