1 案例概述
实现输入product的quantity,price后计算amount,验证product id是否为空。完成prodcut编辑后自动计算order total amount,以及计算create by,create on 等信息。
Data
- ROOT(ORDER_ID, TOTAL_AMOUNT_VAL, TOTAL_AMOUNT_CUR, include admin structure)
- ITEM(PRODUCT_ID, AMOUNT_VAL, AMOUNT_CUR, QUANTITY_VAL, QUANTITY_UNI,PRICE_VAL, PRICE_CUR)
Determination
- ROOT
DET_ADMIN_DATA (ROOT has Admin Data and related determination)
DET_ROOT_AM (call action CALC_TOTAL_AMOUNT) - ITEM
CALC_AMOUNT (after modify)
Validation
- ITEM
VAL_BO_CONSISTENCY (validate product exist or not, if not, raise a warning message)
Action
- ITEM
CALC_TOTAL_AMOUNT
2 Determination
ROOT
- DET_ADMIN_DATA
用来记录create on,create by,changed on,changed by相关信息,这里不需要我们自己实现,技术也没达到,套用就行。 - DET_ROOT_AM
在子节点ITEM编辑完成后,根据ITEM的AMOUNT计算ROOT节点TOTAL AMOUNT。调用Action CALC_TOTAL_AMOUNT实现。调用action一般采用如下方法,其中,iv_act_key
表示所要调用的action key,it_key
表示节点下每一条数据的key。
触发条件是在ROOT的子节点ITEM Create和Update ,After Modify,前提条件是
io_modify->do_action(
EXPORTING
iv_act_key = ZIF_STE_ORDER_C=>SC_ACTION-ROOT-CALC_TOTAL_AMOUNT " Action
it_key = it_key " Key Table
* is_parameters =
* IMPORTING
* eo_message = " Message Object
* et_failed_key = " Key Table
* eo_change = " Interface of Change Object
* et_data =
).
ITEM
- CALC_AMOUNT
触发条件是After Modify。
在输入ITEM相关数据后,根据输入的PRICE_VAL, QUANTITY_VAL计算AMOUNT_VAL并将结果绑定。难点在于获取输入数据以及绑定结果。具体操作如下:
io_read->retrieve
是获取输入值,iv_node
是当前node的key值,it_key
表示当前节点下每一条数据key,iv_fill_data
与et_data
绑定使用表示填充值,et_data
表示结果集,iv_before_image
为true表示读取修改前的值
/scmtms/cl_mod_helper=>mod_update_single
是将结果绑定到字段,is_data
是要绑定的值,iv_node
是当前node的key值,iv_key
是每一行数据的key值,it_changed_fields
是要被绑定值的key值。
对于绑定值有两种方法,注释掉的部分为方法二。
DATA: lt_item TYPE zste_t_ord_item,
ls_item TYPE zste_s_ord_item,
lt_mod TYPE /bobf/t_frw_modification,
lr_item TYPE REF TO zste_s_ord_item.
FIELD-SYMBOLS: <ls_mod> LIKE LINE OF lt_mod.
WRITE: ls_item-product_id.
io_read->retrieve(
EXPORTING
iv_node = zif_ste_order_c=>sc_node-item " Node Name
it_key = it_key " Key Table
* iv_before_image = ABAP_FALSE " Data Element for Domain BOOLE: TRUE (="X") and FALSE (=" ")
* iv_fill_data = ABAP_TRUE " Data element for domain BOOLE: TRUE (='X') and FALSE (=' ')
* it_requested_attributes = " List of Names (e.g. Fieldnames)
IMPORTING
* eo_message = " Message Object
et_data = lt_item " Data Return Structure
* et_failed_key = " Key Table
* et_node_cat = " Node Category Assignment
).
LOOP AT lt_item INTO ls_item.
ls_item-amount_val = ls_item-price_val * ls_item-quantity_val.
ls_item-amount_cur = ls_item-price_cur.
/scmtms/cl_mod_helper=>mod_update_single(
EXPORTING
is_data = ls_item
iv_node = zif_ste_order_c=>sc_node-item " Node
iv_key = ls_item-key " NodeID
it_changed_fields = VALUE #( ( zif_ste_order_c=>sc_node_attribute-item-amount_val )
( zif_ste_order_c=>sc_node_attribute-item-amount_cur ) ) " List of Names (e.g. Fieldnames)
* iv_autofill_fields = 'X' " 'X' -> all not readonly fields will be determined
* iv_bo_key = " Business Object
* importing
* es_mod = " Change
CHANGING
ct_mod = lt_mod " Changes
).
ENDLOOP.
* LOOP AT lt_item INTO ls_item.
* ls_item-amount_val = ls_item-price_val * ls_item-quantity_val.
* ls_item-amount_cur = ls_item-price_cur.
*
* APPEND INITIAL LINE TO lt_mod ASSIGNING <ls_mod>.
* CREATE DATA lr_item.
* lr_item->* = ls_item.
* <ls_mod>-change_mode = /bobf/if_frw_c=>sc_modify_update.
* <ls_mod>-association = zif_ste_order_c=>sc_association-root-item.
* <ls_mod>-source_node = zif_ste_order_c=>sc_node-root.
* <ls_mod>-node = zif_ste_order_c=>sc_node-item.
* <ls_mod>-key = lr_item->key.
* <ls_mod>-data = lr_item.
* ENDLOOP.
IF lt_mod IS NOT INITIAL.
io_modify->do_modify( it_modification = lt_mod ).
ENDIF.
3 Validation
ITEM
-
VAL_BO_CONSISTENCY
触发条件
验证ITEM输入是否存在PRODUCT ID。主要难点在于错误信息显示,实现如下
首先要在T-Code:se91
种创建message,/scmtms/cl_msg_helper=>add_message
用于显示提示信息
DATA: ls_item TYPE zste_s_ord_item,
lt_item TYPE zste_t_ord_item,
lv_msg TYPE string,
ls_msg TYPE symsg.
CLEAR eo_message.
io_read->retrieve(
EXPORTING
iv_node = zif_ste_order_c=>sc_node-item " Node Name
it_key = it_key " Key Table
* iv_before_image = ABAP_FALSE " Data Element for Domain BOOLE: TRUE (="X") and FALSE (=" ")
* iv_fill_data = ABAP_TRUE " Data element for domain BOOLE: TRUE (='X') and FALSE (=' ')
* it_requested_attributes = " List of Names (e.g. Fieldnames)
IMPORTING
* eo_message = " Message Object
et_data = lt_item " Data Return Structure
* et_failed_key = " Key Table
* et_node_cat = " Node Category Assignment
).
LOOP AT lt_item INTO ls_item.
IF ls_item-product_id IS INITIAL.
MESSAGE e001(zste_order) INTO lv_msg.
MOVE-CORRESPONDING sy TO ls_msg.
/scmtms/cl_msg_helper=>add_message(
EXPORTING
* iv_bopf_location_key = " Det/Val execution node instance key
is_msg = ls_msg " Structure of Message Variables
iv_bo_key = is_ctx-bo_key " Business Object
iv_node = is_ctx-node_key " Node Name
iv_key = ls_item-key " Key
iv_attribute = zif_ste_order_c=>sc_node_attribute-item-product_id " Field Name
iv_detlevel = /scmtms/cl_applog_helper=>sc_al_detlev_default " Application Log: Level of detail
iv_probclass = /scmtms/cl_applog_helper=>sc_al_probclass_important " Application log: Message problem class
* iv_add_context_info = ABAP_FALSE " Generate BO instance specific message context
CHANGING
co_message = eo_message " Interface of Message Object
).
/scmtms/cl_common_helper=>insert_key(
EXPORTING
iv_key = ls_item-key " NodeID
* is_key = " Node Key
CHANGING
ct_key = et_failed_key " Key Table
).
ENDIF.
ENDLOOP.
4 Action
ROOT
- CALC_TOTAL_AMOUNT
难点主要在于ROOT节点获取子节点ITEM的值,以及将计算结果绑定到对应字段。
ROOT节点获取子节点ITEM的值使用io_read->retrieve_by_association
,此方法中参数iv_fill_data
的默认值为false;在将结果绑定到对应字段时,应注意先读取数据值
DATA: lt_item TYPE zste_t_ord_item,
ls_item TYPE zste_s_ord_item,
ls_root TYPE zste_s_ord_root_k,
lt_root TYPE zste_t_ord_root_k,
lt_mod TYPE /bobf/t_frw_modification.
io_read->retrieve_by_association(
EXPORTING
iv_node = zif_ste_order_c=>sc_node-root " Node Name
it_key = it_key " Key Table
iv_association = zif_ste_order_c=>sc_association-root-item " Name of Association
* is_parameters =
* it_filtered_attributes = " List of Names (e.g. Fieldnames)
iv_fill_data = abap_true " Data Element for Domain BOOLE: TRUE (="X") and FALSE (=" ")
* iv_before_image = ABAP_FALSE " Data Element for Domain BOOLE: TRUE (="X") and FALSE (=" ")
* it_requested_attributes = " List of Names (e.g. Fieldnames)
IMPORTING
* eo_message = " Message Object
et_data = lt_item " Data Return Structure
* et_key_link = " Key Link
* et_target_key = " Key Table
* et_failed_key = " Key Table
).
io_read->retrieve(
EXPORTING
iv_node = zif_ste_order_c=>sc_node-root " Node Name
it_key = it_key " Key Table
* iv_before_image = ABAP_FALSE " Data Element for Domain BOOLE: TRUE (="X") and FALSE (=" ")
* iv_fill_data = ABAP_TRUE " Data element for domain BOOLE: TRUE (='X') and FALSE (=' ')
* it_requested_attributes = " List of Names (e.g. Fieldnames)
IMPORTING
* eo_message = " Message Object
et_data = lt_root " Data Return Structure
* et_failed_key = " Key Table
* et_node_cat = " Node Category Assignment
).
LOOP AT lt_root INTO ls_root.
LOOP AT lt_item INTO ls_item.
ls_root-total_amount_val = ls_root-total_amount_val + ls_item-amount_val.
ls_root-total_amount_cur = ls_item-amount_cur.
ENDLOOP.
/scmtms/cl_mod_helper=>mod_update_single(
EXPORTING
is_data = ls_root
iv_node = zif_ste_order_c=>sc_node-root " Node
iv_key = ls_root-key " NodeID
it_changed_fields = VALUE #( ( zif_ste_order_c=>sc_node_attribute-root-total_amount_val )
( zif_ste_order_c=>sc_node_attribute-root-total_amount_cur ) ) " List of Names (e.g. Fieldnames)
* iv_autofill_fields = 'X' " 'X' -> all not readonly fields will be determined
* iv_bo_key = " Business Object
* IMPORTING
* es_mod = " Change
CHANGING
ct_mod = lt_mod " Changes
).
ENDLOOP.
IF lt_mod IS NOT INITIAL.
io_modify->do_modify( it_modification = lt_mod ).
ENDIF.