从 ABAP CDS 视图调用 BRF+ 规则?

Call BRF+ rule from ABAP CDS view?

首先,我正在使用 ABAP 7.50 和 Oracle DB 在 ECC 中进行开发。我有一个 BRF+ 规则,对于给定的邮政编码 return 给我一个特定的承包商 ID。

只有 2 个可能的承包商 ID,但每个 ID 的邮政编码都是一组基于范围和唯一值的规则。

简化规则示例:

IF postalCode >= 1000 and postalCode <= 2000 THEN Contractor1
ELSE postalCode = 2001 THEN Contractor2
ELSE postalCode = 2002 THEN Contractor1
ELSE Contractor2

现在我有一个 ABAP CDS,其中 return 是工单信息,我还需要它 return header 中的供应商 ID。我能否以某种方式使用工作订单邮政编码调用 BRF+ 并仅使用 CDS 获取供应商 ID?

我想这样做,因为 CDS 直接公开为 ODATA 服务。否则我可以使用 OpenSQL 查询数据库,然后填写剩余的字段。

编辑:我将 Haojie 的答案标记为正确,尽管它只能从 7.51 版本开始。对于较低版本 - 据我所知 - 除了从 CDS 视图读取后添加逻辑之外没有其他解决方案(在网关中或不直接从视图创建 ODATA 服务,而是使用 ABAP 添加缺少的信息。

您可以使用 ABAP CDS Virtual Element

您需要在工作订单 CDS 之上构建另一个 CDS 视图,并创建一个新的人工字段(如 VendorID)并对其进行注释。

 define view my_cds_view 
    as select from WorkOrder
{
    ...
     @ObjectModel.readOnly: true
     @ObjectModel.virtualElement
     @ObjectModel.virtualElementCalculatedBy: 'cl_brf_plus_vendor_id'
    cast('' as abap.lifnr ) as VendorID       
    ...
 } 

创建一个Classcl_brf_plus_vendor_id来实现if_sadl_exit_calc_element_read

CLASS cl_brf_plus_vendor_id DEFINITION
    PUBLIC
    FINAL
    CREATE PUBLIC .

    PUBLIC SECTION.
    INTERFACES:
    if_sadl_exit_calc_element_read.

    PROTECTED SECTION.
    PRIVATE SECTION.
ENDCLASS.


CLASS cl_brf_plus_vendor_id IMPLEMENTATION.

   METHOD if_sadl_exit_calc_element_read~get_calculation_info.

   ENDMETHOD.


   METHOD if_sadl_exit_calc_element_read~calculate.

       CHECK NOT it_original_data IS INITIAL.

       DATA lt_calculated_data TYPE STANDARD TABLE OF my_cds_view WITH DEFAULT KEY.

       MOVE-CORRESPONDING it_original_data TO lt_calculated_data.

       LOOP AT lt_calculated_data ASSIGNING FIELD-SYMBOL(<ls_calculated_data>).
         **"Get the postal code and call BRF+ to 
           "have the value of artificial field VendorID.** 

       ENDLOOP.

       MOVE-CORRESPONDING lt_calculated_data TO ct_calculated_data.

    ENDMETHOD.

  ENDCLASS.

将 my_cds_view 作为数据源添加到您的 Gateway 项目。

您可以利用 CDS table 函数来完成您的任务及其能力 to store intermediate results in internal table. It is yet available since 7.40 SP05 when AMDP was released, and table functions are available since 7.50

假设您有 CDS 视图,其中包含由 table 函数 zcl_cds_ord

实现的订单
@EndUserText.label: 'BRF function'
@AccessControl.authorizationCheck: #NOT_REQUIRED
define table function ZCDS_ORD_FUNC
returns {
  mandt       :mandt;
  ebeln       :ebeln;
  bstyp       :ebstyp;
  vendor_id   :lifnr;
}
implemented by method zcl_cds_ord=>get_vendor;

您想通过 BRF+ 按订单 ID 获取每个订单的供应商 ID。

为了完成你 table 函数实现的任务 class 你应该创建单独的方法来调用 BRF+ 并更新中间 itab 并在主 table 函数方法中重新读取您的内部 table 进入最终 CDS 视图。

可能实现 AMDP class:

CLASS zcl_cds_ord DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC.

  PUBLIC SECTION.
    TYPES: BEGIN OF ty_orders,
             mandt     TYPE mandt,
             ebeln     TYPE ebeln,
             bstyp     TYPE ebstyp,
             vendor_id TYPE lifnr,
           END OF ty_orders,
           tty_orders TYPE STANDARD TABLE OF ty_orders.

    INTERFACES if_amdp_marker_hdb.
    CLASS-METHODS get_vendor FOR TABLE FUNCTION zcds_ord_func.
    METHODS call_brf CHANGING it_orders TYPE tty_orders.
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.

CLASS zcl_cds_ord IMPLEMENTATION.
  METHOD get_vendor BY DATABASE FUNCTION
          FOR HDB
          LANGUAGE SQLSCRIPT
          OPTIONS READ-ONLY.

    itab_orders = SELECT mandt,
                         ebeln,
                         bstyp,
                         '' AS vendor_id
                  FROM ekko;

    CALL call_brf CHANGING itab_orders.

    RETURN SELECT mandt, ebeln, bstyp, vendor_id
    FROM :itab_orders.
  ENDMETHOD.

  METHOD call_brf.
    DATA: lo_fuction    TYPE REF TO if_fdt_function.

* Get BRFplus function
    lo_fuction ?= cl_fdt_factory=>if_fdt_factory~get_instance( )->get_function( '50E549C2C40B1ED6A69FCB34B9365358' ).

* Set the BRFplus function context ( input variables )
    DATA(lo_context) = lo_fuction->get_process_context( ).

    LOOP AT it_orders ASSIGNING FIELD-SYMBOL(<fs_order>).
      lo_context->set_value( : iv_name  = 'ORDER_ID' ia_value = <fs_order>-ebeln   ) .
* Process the BRFplus function
      lo_fuction->process( EXPORTING io_context =  lo_context
                           IMPORTING eo_result  =  DATA(lo_result) ).

* Retrieve the BRFplus function result
      lo_result->get_value( IMPORTING ea_value =  <fs_order>-vendor_id ).
    ENDLOOP.
  ENDMETHOD.
ENDCLASS.

请注意,在 CDS 实现方法(if_amdp_marker_hdb 接口)中,您只能使用 SQLScript 语句,但在其他方法中,您可以使用 ABAP。

上面答案中给出的以下代码片段在我看来不起作用。 您不能在 AMDP 方法内调用 ABAP 方法,并且 CALL ... CHANGING 在这种情况下甚至不是语法的一部分,它看起来像是 SQLscript 和 ABAP 的混合体。

  METHOD get_vendor BY DATABASE FUNCTION
          FOR HDB
          LANGUAGE SQLSCRIPT
          OPTIONS READ-ONLY.

    itab_orders = SELECT mandt,
                         ebeln,
                         bstyp,
                         '' AS vendor_id
                  FROM ekko;

    CALL call_brf CHANGING itab_orders.

    RETURN SELECT mandt, ebeln, bstyp, vendor_id
    FROM :itab_orders.
  ENDMETHOD.

上述@Suncatcher 解决方案中的 CALL 关键字不起作用,它只对调用 hana 数据库或其他 amdp 中已有的过程有用 class(因为这是在 hana 中db 也是),从来没有 abap class 方法。