如何动态控制 CRM attachment UI 的可编辑性(editability)

在企业应用里,根据用户身份,动态控制 attachment UI 的可编辑性,是一个常见需求。

在 ABAP 技术栈的系统里,权限控制(Authorization Control)是采取 ABAP 的 Authorization Object 实现的。

本文通过一个具体的例子,介绍如何动态控制 CRM attachment UI 的可编辑性(editability)。

下图我开发了一个 WebClient UI,通过一个叫做 Allow Edit 的 checkbox,动态控制 attachment UI 工具栏上这些按钮的 enable 与否状态。

这套解决方案能够工作的技术前提是,在 reuse Component GS_CM 里,提供了一个叫做 ATTRIBUTES 的 value node,这个 value node 通过 reuse Component 的 Component controller 暴露出来,可以被其他组件绑定。

在SAP CRM系统中,WebClient UI开发技术是一项关键的任务,它允许开发人员创建灵活且功能强大的用户界面,以满足企业客户关系管理的需求。在WebClient UI开发中,value node(值节点)和model node(模型节点)是两个重要的概念,它们在数据管理和界面设计中扮演着不同的角色。

Value Node(值节点)

Value node是WebClient UI中的一种数据结构,用于表示应用程序数据的一个节点。它主要负责存储和管理用户界面上的数据。在ABAP层面,value node通过数据字典中的数据元素来定义,并且在CRM应用程序中,它通常与业务对象相关联。Value node中的数据通常用于显示和编辑用户界面上的字段。

Model Node(模型节点)

Model node也是WebClient UI中的一种数据结构,但它的作用更加宽泛,不仅仅限于存储数据。Model node负责管理应用程序的状态和行为,它包含了与界面逻辑相关的信息,例如事件处理、导航和其他控制逻辑。与value node不同,model node的数据可以来自多个value node,它的目标是提供一个整体的应用程序状态管理。

下面 reuse Component GS_CM 的 Component controller 代码里,首先检查当前的 BOR type 是否 valid,如果检测结果 invalid,会自动将 attachment UI 设置成 readonly 模式。

具体的开发步骤:

  1. 为 checkbox 控件的 status change 事件,创建一个 event handler,引入一个全局变量 存储 checkbox 状态:

  1. 在 wrapper Component 里创建一个新的 value node,同样取名 ATTRIBUTE

重新实现 INIT 方法:

 method IF_BSP_MODEL~INIT.
  super->if_bsp_model~init( id    = id
                            owner = owner ).
  mr_owner ?= owner.
  DATA: lv_struct_ref TYPE REF TO crmt_cm_comp_st,
        lv_value_node TYPE REF TO cl_bsp_wd_value_node,
        lv_bo_coll    TYPE REF TO if_bol_bo_col.
  CREATE DATA lv_struct_ref.
  CREATE OBJECT lv_value_node
    EXPORTING
      iv_data_ref = lv_struct_ref.
  CREATE OBJECT lv_bo_coll
    TYPE
      cl_crm_bol_bo_col.
  lv_bo_coll->add( lv_value_node ).
  set_collection( lv_bo_coll ).
  CL_ZSMCATT_BSPWDCOMPONENT_IMPL=>GO_ATTR_WRAPPER = me->collection_wrapper.
  endmethod.

重新实现 ON_NEW_FOCUS:

 method ON_NEW_FOCUS.
     DATA:
     lr_entity          TYPE REF TO cl_crm_bol_entity,
     lr_parent          TYPE REF TO cl_crm_bol_entity,
     lv_entity_name     TYPE string,
     ls_cm_attr         TYPE crmt_cm_comp_st,
     lv_product_type    TYPE comt_product_type,
     lr_bo_attr         TYPE REF TO if_bol_bo_property_access,
     ls_prtyp_cust      TYPE coms_prtyp_cust,
     lv_object_guid     TYPE ib_recno_16,
     lv_current         TYPE flag,
     ls_button          TYPE crmt_thtmlb_button.
  CHECK focus_bo IS BOUND.
  lr_entity ?= focus_bo.
  lv_entity_name = lr_entity->get_name( ).
  IF CL_ZSMCATT_BSPWDCOMPONENT_IMPL=>gv_can_edit = 'X'.
    ls_cm_attr-display = ''.
  ELSE.
    ls_cm_attr-display = 'X'.
  ENDIF.
  CHECK CL_ZSMCATT_BSPWDCOMPONENT_IMPL=>GO_ATTR_WRAPPER IS NOT INITIAL.
  lr_bo_attr = CL_ZSMCATT_BSPWDCOMPONENT_IMPL=>GO_ATTR_WRAPPER->get_current( ).
  CHECK lr_bo_attr IS BOUND.
  lr_bo_attr->set_properties( ls_cm_attr ).
  endmethod.
  1. 实现 ZSMCATTR component controller 的 WD_USAGE_INITIALIZE
CALL METHOD iv_usage->bind_context_node
        EXPORTING
          iv_controller_type  = cl_bsp_wd_controller=>co_type_custom
          iv_name             = 'ZSMCATT/CMBO'
          iv_target_node_name = 'ATTRIBUTE'                "#EC NOTEXT
          iv_node_2_bind      = 'ATTRIBUTES'.                "#EC NOTEXT
lr_cuco_attachement ?= get_custom_controller( 'ZSMCATT/CMBO' ).
IF lr_cuco_attachement IS BOUND.
        lr_property = me>typed_context->socialpost->collection_wrapper->get_current( ).
        lr_cuco_attachement->typed_context->cmbo->on_new_focus( lr_property ).
        lr_cuco_attachement->typed_context->attribute->on_new_focus( lr_property ).
ENDIF. 

上述三个步骤实现完毕后,即可达到本文开头介绍的效果。