简体   繁体   English

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

[英]Call BRF+ rule from ABAP CDS view?

First of all, I'm developing in ECC with ABAP 7.50 and Oracle DB.首先,我正在使用 ABAP 7.50 和 Oracle DB 在 ECC 中进行开发。 I have a BRF+ rule that for a given postal code returns me a specific contractor ID.我有一个 BRF+ 规则,对于给定的邮政编码,我会返回一个特定的承包商 ID。

There are only 2 possible contractor IDs, but the postal codes for each one are a set of rules based on ranges and unique values.只有 2 个可能的承包商 ID,但每个 ID 的邮政编码都是一组基于范围和唯一值的规则。

Simplified rule example:简化规则示例:

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

Now I have an ABAP CDS that returns a Work Order information and I need it to also return the vendor ID in the header. Can I somehow call the BRF+ with the work order postal code and get the vendor ID using only CDS?现在我有一个返回工单信息的 ABAP CDS,我还需要它返回 header 中的供应商 ID。我能否以某种方式使用工单邮政编码调用 BRF+ 并仅使用 CDS 获取供应商 ID?

I would like to do that because the CDS is directly exposed as an ODATA service.我想这样做是因为 CDS 直接公开为 ODATA 服务。 Otherwise I can use OpenSQL to query the DB and then fill the remaining field.否则我可以使用 OpenSQL 查询数据库,然后填写剩余字段。

Edit: I marked Haojie answer as correct, even though it's only possible from 7.51 version.编辑:我将 Haojie 的答案标记为正确,即使它只能从 7.51 版本开始。 For lower versions -to my knowledge- there is no solution other than adding the logic after reading from the CDS view (in Gateway or not creating the ODATA service directly from the view, but use ABAP to add the missing information.对于较低版本 - 据我所知 - 除了从 CDS 视图读取后添加逻辑之外没有其他解决方案(在网关中或不直接从视图创建 ODATA 服务,而是使用 ABAP 添加丢失的信息。

You can use ABAP CDS Virtual Element .您可以使用ABAP CDS 虚拟元素

You need to build another CDS view on top of the Work Order CDS and create a new artificial Field like VendorID and annotate it.您需要在工单 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       
    ...
 } 

Create a Class cl_brf_plus_vendor_id to implement if_sadl_exit_calc_element_read创建一个类 cl_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.

Add my_cds_view as data source to your Gateway project.将 my_cds_view 作为数据源添加到您的网关项目。

You can utilize CDS table functions for your task and their capability to store intermediate results in internal table .您可以将 CDS 表函数用于您的任务及其将中间结果存储在内部表中的能力 It is yet available since 7.40 SP05 when AMDP was released, and table functions are available since 7.50 .从 7.40 SP05 发布 AMDP 开始,它仍然可用,并且从 7.50 开始可以使用表函数。

Supposing you has CDS view with orders which is implemented by table function zcl_cds_ord假设您有订单的 CDS 视图,该视图由表函数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;

You want to fetch vendor ID for each order through BRF+ by order ID.您想通过 BRF+ 按订单 ID 获取每个订单的供应商 ID。

To fulfill the task in you table function implementing class you should create separate method that will call BRF+ and update intermediate itab and in the main table function method re-read your internal table into final CDS view.要在表函数实现类中完成任务,您应该创建单独的方法来调用 BRF+ 并更新中间 itab,并在主表函数方法中将内部表重新读取到最终的 CDS 视图中。

Possible implementation of AMDP class: AMDP 类的可能实现:

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.

Note that in CDS-implementing method ( if_amdp_marker_hdb interface) you can use only SQLScript statements, but in other methods you can use ABAP.请注意,在 CDS 实现方法( if_amdp_marker_hdb接口)中,您只能使用SQLScript语句,但在其他方法中,您可以使用 ABAP。

The below code snippet given in above answer is in my mind not working.上面答案中给出的以下代码片段在我看来不起作用。 You cannot call an ABAP method inside an AMDP method and CALL ... CHANGING in this case is not even part of the syntax and it looks like a mixture between SQLscript and 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.

The CALL keyword from the @Suncatcher solution above does not work and it is only useful to call another procedure already in the hana db or other amdp that is in this class(as this is in the hana db too), never an abap class method.上面@Suncatcher 解决方案中的 CALL 关键字不起作用,它只对调用 hana db 中已有的另一个过程或此类中的其他 amdp 有用(因为这也在 hana db 中),从来没有 abap class 方法.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM