文章背景:
项目组员在创建SM30的时候,发现了下图的报错,原因是因为自建表中的地址编号ADRNR字段使用了标准的数据元素AD_ADDRNUM,当使用包含该数据元素的视图在SM30进行维护时,就会出现下面的报错AM287。
后续了解到,项目成员的需求这里要维护的地址编号并不是ADRC中的地址主数据,而是一个流水号用于区分业务信息,所以改成其他自定义数据元素后重新生成视图即可解决该问题。
正文:
再回到这个问题进一步了解后发现,这里是可以直接维护ADRC中地址主数据的信息的,又称之为中央地址管理(Business Address Services),如果想要在SM30维护地址信息,就需要按照上图的提示去做进一步配置,配置如下:
自建表信息:
SM30:TSADRV
SM30:TSAD7
添加完上面两个配置后,重新生成维护视图,即可发现,不会有之前的报错,并且SM30标准界面上方出现了一个按钮。
点击这个按钮,即可进行地址主数据信息的维护,并将信息更新回ADRC表中,不过ADRNR字段是会被标准逻辑隐藏起来的。
点击维护地址按钮,就会发现,跟前台标准事务代码中维护地址信息的窗口是一样的。
这让我想起了之前业务顾问提到的一个需求,想在标准界面的增强页签中添加一个这样的按钮,用来维护客户的自定义地址信息,当时觉得可能没那么好做,不过在对SM30这个按钮进行调试后,发现其实并不难实现,主要使用的函数包含下面几个:
ADDR_DIALOG:根据参数maint_mode决定弹窗显示的形式(CREATE / CHANGE / DISPLAY)
ADDR_MEMORY_CLEAR:实际写代码测试发现如果是新增自定义地址主数据之前,需要清空掉一些缓存,否则会有报错,调用该函数可以进行清空。
ADDR_INSERT:地址主数据创建。
ADDR_UPDATE:地址主数据修改。
ADDR_DELETE:地址主数据删除(未测试)。
ADDR_NUMBER_GET:创建之后,使用该函数来获取内存中生成的地址主数据编号ADRNR。
ADDR_SINGLE_SAVE:传入地址编号,进行数据库提交保存。
测试程序:
以下为测试demo程序,用来模拟当初那个需求的实现,逻辑并没有写的很严谨,只是为了测试可行性。
主要测试逻辑为:当地址号为空时,点击按钮会进行创建,创建完成后将地址号反写回屏幕,再次点击按钮时,如果地址号有值,则以显示模式或者更改模式呼出弹窗。
测试源码:
*&---------------------------------------------------------------------*
*& Report ZTESTADRC_DIALOG
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT ztestadrc_dialog.
TYPES:
tt_handle TYPE STANDARD TABLE OF addr1_dia,
tt_values TYPE STANDARD TABLE OF addr1_data.
DATA:
gv_adrnr TYPE adrc-addrnumber,
gv_okcode TYPE sy-ucomm,
okcode TYPE sy-ucomm.
CALL SCREEN 9000.
*&---------------------------------------------------------------------*
*& Module USER_COMMAND_9000 INPUT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
MODULE user_command_9000 INPUT.
gv_okcode = okcode.
CLEAR okcode.
CASE gv_okcode.
WHEN 'BACK'.
LEAVE PROGRAM.
WHEN 'MAINTAIN'.
PERFORM frm_maintain_adrc.
WHEN OTHERS.
ENDCASE.
ENDMODULE.
*&---------------------------------------------------------------------*
*& Module STATUS_9000 OUTPUT
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
MODULE status_9000 OUTPUT.
IF gv_adrnr IS NOT INITIAL.
LOOP AT SCREEN.
IF screen-name = 'GV_ADRNR'.
screen-input = 0.
MODIFY SCREEN.
ENDIF.
ENDLOOP.
ENDIF.
ENDMODULE.
*&---------------------------------------------------------------------*
*& Form frm_maintain_adrc
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
FORM frm_maintain_adrc .
DATA:
lv_mode TYPE addr1_dia-maint_mode,
lt_handle TYPE STANDARD TABLE OF addr1_dia,
ls_handle TYPE addr1_dia,
lt_values TYPE STANDARD TABLE OF addr1_data,
ls_values TYPE addr1_data,
lv_ok_code TYPE sy-ucomm.
IF gv_adrnr IS INITIAL.
lv_mode = 'CREATE'.
ELSE.
* lv_mode = 'CHANGE'.
lv_mode = 'DISPLAY'.
ENDIF.
CASE lv_mode.
WHEN 'CREATE'.
ls_handle-handle = 'TEST_CREATE'.
ls_handle-maint_mode = lv_mode.
ls_handle-addr_group = 'ZA01'.
WHEN 'CHANGE'.
ls_handle-addrnumber = gv_adrnr.
ls_handle-maint_mode = lv_mode.
ls_handle-addr_group = 'ZA01'.
WHEN 'DISPLAY'.
ls_handle-addrnumber = gv_adrnr.
ls_handle-maint_mode = lv_mode.
ls_handle-addr_group = 'ZA01'.
WHEN OTHERS.
ENDCASE.
APPEND ls_handle TO lt_handle.
CLEAR ls_handle.
* Maintain address info
CALL FUNCTION 'ADDR_DIALOG'
* EXPORTING
* CHECK_ADDRESS = 'X'
* SUPPRESS_TAXJURCODE_CHECK = ' '
* IV_TIME_DEPENDENT_COMM_DATA = ' '
IMPORTING
ok_code = lv_ok_code
TABLES
number_handle_tab = lt_handle
values = lt_values
EXCEPTIONS
address_not_exist = 1
group_not_valid = 2
parameter_error = 3
internal_error = 4
OTHERS = 5.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
CASE lv_mode.
WHEN 'CREATE'.
PERFORM frm_adrc_insert USING lt_handle lt_values.
WHEN 'CHANGE'.
PERFORM frm_adrc_update USING lt_handle lt_values.
WHEN OTHERS.
ENDCASE.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_ADRC_INSERT
*&---------------------------------------------------------------------*
*& Insert new records
*&---------------------------------------------------------------------*
*& --> LT_VALUES
*&---------------------------------------------------------------------*
FORM frm_adrc_insert USING ut_handle TYPE tt_handle
ut_values TYPE tt_values.
DATA:
ls_hanle TYPE addr1_dia,
ls_values TYPE addr1_data,
ls_addrref TYPE addr_ref.
READ TABLE ut_handle INTO ls_hanle INDEX 1.
READ TABLE ut_values INTO ls_values INDEX 1.
* CALL FUNCTION 'ADDR_MEMORY_CLEAR_COMMIT_WORK'.
CALL FUNCTION 'ADDR_MEMORY_CLEAR'
EXPORTING
force = 'X'
EXCEPTIONS
unsaved_data_exist = 1
internal_error = 2
OTHERS = 3.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
CALL FUNCTION 'ADDR_INSERT'
EXPORTING
address_data = ls_values
address_group = ls_hanle-addr_group
address_handle = ls_hanle-handle
EXCEPTIONS
address_exists = 1
parameter_error = 2
internal_error = 3
OTHERS = 4.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid
TYPE sy-msgty
NUMBER sy-msgno
WITH sy-msgv1
sy-msgv2
sy-msgv3
sy-msgv4.
CASE sy-subrc.
WHEN 1.
RAISE address_exists.
WHEN 2.
RAISE parameter_error.
WHEN 3 OR 4.
RAISE internal_error.
ENDCASE.
ELSE.
ls_addrref-appl_table = 'ADRC'.
ls_addrref-appl_field = 'ADDRNUMBER'.
ls_addrref-appl_key(3) = sy-mandt.
ls_addrref-addr_group = 'ZA01'.
CALL FUNCTION 'ADDR_NUMBER_GET'
EXPORTING
address_handle = ls_hanle-handle
address_reference = ls_addrref
IMPORTING
address_number = gv_adrnr
EXCEPTIONS
address_handle_not_exist = 1
internal_error = 2
parameter_error = 3
OTHERS = 4.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid
TYPE sy-msgty
NUMBER sy-msgno
WITH sy-msgv1
sy-msgv2
sy-msgv3
sy-msgv4.
CASE sy-subrc.
WHEN 1.
RAISE address_exists.
WHEN 2.
RAISE parameter_error.
WHEN 3 OR 4.
RAISE internal_error.
ENDCASE.
ELSE.
CALL FUNCTION 'ADDR_SINGLE_SAVE'
EXPORTING
address_number = gv_adrnr
EXCEPTIONS
address_not_exist = 1
person_not_exist = 2
address_number_missing = 3
reference_missing = 4
internal_error = 5
database_error = 6
parameter_error = 7
OTHERS = 8.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid
TYPE sy-msgty
NUMBER sy-msgno
WITH sy-msgv1
sy-msgv2
sy-msgv3
sy-msgv4.
CASE sy-subrc.
WHEN 1.
RAISE address_not_exist.
WHEN 2.
RAISE person_not_exist.
WHEN 3.
RAISE address_number_missing.
WHEN 4.
RAISE reference_missing.
WHEN 5 OR 8.
RAISE internal_error.
WHEN 6.
RAISE database_error.
WHEN 7.
RAISE parameter_error.
ENDCASE.
ELSE.
MESSAGE |{ gv_adrnr } create successed| TYPE 'S'.
ENDIF.
ENDIF.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_ADRC_UPDATE
*&---------------------------------------------------------------------*
*& Update address records
*&---------------------------------------------------------------------*
*& --> LT_VALUES
*&---------------------------------------------------------------------*
FORM frm_adrc_update USING ut_handle TYPE tt_handle
ut_values TYPE tt_values.
DATA:
ls_hanle TYPE addr1_dia,
ls_values TYPE addr1_data,
ls_addrref TYPE addr_ref.
READ TABLE ut_handle INTO ls_hanle INDEX 1.
READ TABLE ut_values INTO ls_values INDEX 1.
CALL FUNCTION 'ADDR_UPDATE'
EXPORTING
address_data = ls_values
address_number = gv_adrnr
address_handle = ls_hanle-handle
EXCEPTIONS
address_exists = 1
parameter_error = 2
internal_error = 3
OTHERS = 4.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid
TYPE sy-msgty
NUMBER sy-msgno
WITH sy-msgv1
sy-msgv2
sy-msgv3
sy-msgv4.
CASE sy-subrc.
WHEN 1.
RAISE address_exists.
WHEN 2.
RAISE parameter_error.
WHEN 3 OR 4.
RAISE internal_error.
ENDCASE.
ELSE.
CALL FUNCTION 'ADDR_SINGLE_SAVE'
EXPORTING
address_number = gv_adrnr
EXCEPTIONS
address_not_exist = 1
person_not_exist = 2
address_number_missing = 3
reference_missing = 4
internal_error = 5
database_error = 6
parameter_error = 7
OTHERS = 8.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid
TYPE sy-msgty
NUMBER sy-msgno
WITH sy-msgv1
sy-msgv2
sy-msgv3
sy-msgv4.
CASE sy-subrc.
WHEN 1.
RAISE address_not_exist.
WHEN 2.
RAISE person_not_exist.
WHEN 3.
RAISE address_number_missing.
WHEN 4.
RAISE reference_missing.
WHEN 5 OR 8.
RAISE internal_error.
WHEN 6.
RAISE database_error.
WHEN 7.
RAISE parameter_error.
ENDCASE.
ELSE.
MESSAGE |{ gv_adrnr } update successed| TYPE 'S'.
ENDIF.
ENDIF.
ENDFORM.