Reputation: 1049
First of all, I'm developing in ECC with ABAP 7.50 and Oracle DB. I have a BRF+ rule that for a given postal code returns me a specific contractor 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.
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?
I would like to do that because the CDS is directly exposed as an ODATA service. Otherwise I can use OpenSQL to query the DB and then fill the remaining field.
Edit: I marked Haojie answer as correct, even though it's only possible from 7.51 version. 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.
Upvotes: 3
Views: 5191
Reputation: 1
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.
Upvotes: 0
Reputation: 11
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.
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.
Upvotes: 0
Reputation: 10621
You can utilize CDS table functions for your task and their capability 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.
Supposing you has CDS view with orders which is implemented by table function 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.
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.
Possible implementation of 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.
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.
Upvotes: 0
Reputation: 5713
You can use ABAP CDS Virtual Element.
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.
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
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.
Upvotes: 2