Outbound messaging > Real-time inventory quantities (ATP)
Overview: real-time inventory for materials
Current material stock quantities (usually referred to as Available-to-promise or ATP stock) is widely required e.g. to present the current and orderable number of products in an online store. But ATP is not a static value within SAP systems, unfortunately. To determine current ATP quantities, SAP systems run an on-line calculation that considers reservations, inbound pipeline, planned shipment dates etc.
Therefore, sending real-time ATP stock per material requires the detection of all changes that can affect the stock quantity calculation, an actual calculation and the formatting to make it sendable as a message, with quantity per material, units etc.
ASAPIO provides that with its ATP extraction feature, including pre-delivered example function modules that can be adopted by customers.
Required configuration
SAP Business Objects that can be used and necessary BAdI/User Exit implementation.
Object name | Object type | Configuration |
Sales Order | BUS2032 | Standard |
Purchase Order | BUS2012 | Standard |
Delivery | LIKP | Standard |
Goods Movement | BUS2017 | BAdI (MB_DOCUMENT_UPDATE) |
Material Reservation | ZBUS2093 | User Exit (MBCF0007) |
Create Outbound ATP Configuration
Create Extracting Func. Module:
- Transaction: SE37
- Create function module: Z_ACI_EXTRACTOR_ATP
Example coding:
FUNCTION z_aci_extractor_atp . *"---------------------------------------------------------------------- *"*"Local Interface: *" IMPORTING *" VALUE(IV_INSTANCE) TYPE /ASADEV/AMR_ARIBA_ARIBA_INST *" VALUE(IV_OBJECT) TYPE /ASADEV/AMR_ARIBA_ARIBA_OBJECT *" VALUE(IT_BDCP_LINES) TYPE /ASADEV/ACI_TT_BDCP *" EXPORTING *" VALUE(ET_CSV_LINES) TYPE /ASADEV/AMR_TT_CSV_LINE *" VALUE(ET_RETURN) TYPE /ASADEV/ACI_TT_BAPIRET2 *"---------------------------------------------------------------------- DATA: ls_bdcp TYPE bdcp, ls_csv_line TYPE /asadev/aci_any_string, lv_tmp_event TYPE string, lv_tmp_key TYPE string, lv_keyname TYPE /asadev/aci_head_attr_value, ls_return TYPE bapiret2. " ATP check DATA: lv_werks TYPE werks, lv_matnr TYPE matnr, lv_meins TYPE meins, lt_iwmdvsx TYPE STANDARD TABLE OF bapiwmdvs,"TABLES PARAM ls_iwmdvsx LIKE LINE OF lt_iwmdvsx , lt_iwmdvex TYPE STANDARD TABLE OF bapiwmdve,"TABLES PARAM ls_iwmdvex LIKE LINE OF lt_iwmdvex. DATA: lv_bdcnt TYPE string, lv_req_date TYPE string, lv_req_qty TYPE string, lv_com_date TYPE string, lv_com_qty TYPE string, lv_av_qty_plt TYPE bapicm61v-wkbst, lv_av_qty_plt_str TYPE string, lv_lines TYPE i, ls_return_bapi TYPE bapireturn. DATA: lb_last_row TYPE abap_bool VALUE abap_false. "populate fields of struture and append to itab APPEND ls_iwmdvsx TO lt_iwmdvsx. "populate fields of struture and append to itab APPEND ls_iwmdvex TO lt_iwmdvex. CONSTANTS: lc_auth_obj_rc TYPE xuobject VALUE '/ASADEV/RC', "Mod-001++ lc_auth_fld_rf TYPE fieldname VALUE '/ASADEV/RF', "Mod-001++ lc_message_id TYPE symsgid VALUE '/ASADEV/AMR_MESSAGE', "Mod-001++ lc_message_number TYPE symsgno VALUE '077', "Mod-001++ lc_autch_check_data_proc TYPE /asadev/aci_rfc_auth_check VALUE 'DATA_PROC'."Data processing "Mod-001++ * Check if user can execute RFC AUTHORITY-CHECK OBJECT lc_auth_obj_rc ID lc_auth_fld_rf FIELD lc_autch_check_data_proc. IF sy-subrc <> 0. * No authorization for user &1 to call ACI function! ls_return-type = /asadev/cl_aci_helper=>mc_aci_error. ls_return-id = lc_message_id. ls_return-number = lc_message_number. ls_return-message_v1 = sy-uname. APPEND ls_return TO et_return. CLEAR ls_return. RETURN. ENDIF. /asadev/cl_aci_helper=>get_header_attribute( EXPORTING iv_instance = iv_instance iv_object = iv_object iv_attribute = /asadev/cl_aci_cloudev_helper=>mc_attr_em_key_name RECEIVING rv_value = lv_keyname ). DESCRIBE TABLE it_bdcp_lines LINES lv_lines. LOOP AT it_bdcp_lines INTO ls_bdcp. "lv_tmp_event = ls_bdcp-tabkey(32). "lv_tmp_key = ls_bdcp-tabkey+35(70). "ATP lv_werks = ls_bdcp-tabkey+21(4). lv_matnr = ls_bdcp-tabkey(18). lv_meins = ls_bdcp-tabkey+18(3). IF lv_lines = sy-tabix. lb_last_row = abap_true. ENDIF. *********************************************************** CALL FUNCTION 'BAPI_MATERIAL_AVAILABILITY' EXPORTING plant = lv_werks " Plant material = lv_matnr " Material number unit = lv_meins " Unit of measure for display * check_rule = " Checking rule * stge_loc = " Storage location * batch = " Batch * customer = " Customer number * doc_number = " Document number * itm_number = " Item number * wbs_elem = " WBS Element * stock_ind = " Special Stock Indicator * dec_for_rounding = " No. of decimal places to which rounding should be performed * dec_for_rounding_x = " Updated information in related user data field * read_atp_lock = " Control indicator for availability check * read_atp_lock_x = " Updated information in related user data field * material_evg = " Updated information in related user data field IMPORTING * endleadtme = " End of replenishment lead time av_qty_plt = lv_av_qty_plt " Quantity available at plant level * dialogflag = " Indicator (X = not available, N = no check) return = ls_return_bapi " Indicator (X = not available, N = no check) TABLES wmdvsx = lt_iwmdvsx " Input table (date and quantity) wmdvex = lt_iwmdvex. " Output table (date and ATP quantity) IF sy-subrc EQ 0. lv_av_qty_plt_str = lv_av_qty_plt. CONCATENATE ls_csv_line '{' '"objectType":"' ls_bdcp-tabname '", ' * cl_abap_char_utilities=>newline ' "event":"' lv_tmp_event '", ' cl_abap_char_utilities=>newline ' "werks":"' lv_werks '", ' cl_abap_char_utilities=>newline ' "matnr":"' lv_matnr '", ' cl_abap_char_utilities=>newline ' "meins":"' lv_meins '", ' cl_abap_char_utilities=>newline ' "date":"' sy-datum '", ' cl_abap_char_utilities=>newline ' "quantity":"' lv_av_qty_plt_str '"}' INTO ls_csv_line. AT FIRST. CONCATENATE '{"records":[{"value":[' ls_csv_line INTO ls_csv_line. ENDAT. IF lb_last_row = abap_false. CONCATENATE ls_csv_line ',' INTO ls_csv_line. ENDIF. AT LAST. CONCATENATE ls_csv_line ']}]}' INTO ls_csv_line. ENDAT. APPEND ls_csv_line TO et_csv_lines. CLEAR ls_csv_line. ENDIF. ENDLOOP. ENDFUNCTION.
Create an outbound object configuration:
- Transaction: SPRO
- Go to IMG > ASAPIO Cloud Integrator – Connection and Replication Object Customizing
- Or go directly to transaction: /ASADEV/68000202
- Select the created Connection
- Go to section Outbound Objects
- Add New Entry and specify:
-
- Object: name of the outbound configuration
- Extraction Func. Module: Z_ACI_EXTRACTOR_ATP
- Load Type: Incremental Load
- Trace: activate for testing purposes
-
Set-up Business Object Event Linkage
To consolidate the various triggers into one that contains the necessary key fields to calculate the ATP quantities we have to implement BAdI /ASADEV/TRIGGER_BADI inside /ASADEV/ACI_EVENTS_TRIGGER. In this BAdI implementation we determine the fields MEINS, WERKS and MATNR based on the received event and replace the created change pointers with one that contains these fields that will be needed inside the cutom extractor:
- Transaction: SE18
- BAdI Name: /ASADEV/TRIGGER_BADI
- Filter Val.: Add your Instance and Object that shall use the BAdI implementation.
- Method: /ASADEV/TRIGGER_IF~SET_BDCP_LINES
- Add Implementation:
Example coding:
METHOD /asadev/trigger_if~set_bdcp_lines. DATA: lv_meins TYPE meins, lv_werks TYPE werks, lv_matnr TYPE matnr, lv_len TYPE i, lv_object_type TYPE string, lv_mblnr TYPE mblnr, lv_vbeln TYPE vbeln, lv_ebeln TYPE ebeln, lv_rsnum TYPE rsnum. * Definition of internal tables DATA: "ct_bdcp_lines TYPE /asadev/aci_tt_bdcp, lt_marc TYPE STANDARD TABLE OF marc, lt_vbap TYPE STANDARD TABLE OF vbap, lt_ekpo TYPE STANDARD TABLE OF ekpo, lt_mseg TYPE STANDARD TABLE OF mseg, lt_resb TYPE STANDARD TABLE OF resb, lt_lips TYPE STANDARD TABLE OF lips. DATA: ls_bdcp_lines TYPE bdcp. FIELD-SYMBOLS: TYPE marc, TYPE vbap, TYPE ekpo, TYPE mseg, TYPE resb, TYPE lips. CLEAR ct_bdcp_lines. "Subobjects? Last 7 characters from iv_sender-typeid e.g. zzBUS1001 IF strlen( iv_sender-typeid ) GT 7. lv_len = strlen( iv_sender-typeid ) - 7. lv_object_type = iv_sender-typeid+lv_len(7). ELSE. lv_object_type = iv_sender-typeid. ENDIF. " Select material number, plant and units of messure. CASE lv_object_type. WHEN 'BUS1001'. " Material lv_matnr = iv_sender-instid. SELECT werks INTO CORRESPONDING FIELDS OF TABLE lt_marc FROM marc WHERE matnr = lv_matnr. SELECT SINGLE meins INTO lv_meins FROM mara WHERE matnr = lv_matnr. LOOP AT lt_marc ASSIGNING . CONCATENATE lv_matnr lv_meins -werks INTO ls_bdcp_lines-tabkey RESPECTING BLANKS. APPEND ls_bdcp_lines TO ct_bdcp_lines. " CLEAR ls_bdcp_lines. ENDLOOP. WHEN 'BUS2012'. " Purchase Order lv_ebeln = iv_sender-instid. SELECT matnr meins werks INTO CORRESPONDING FIELDS OF TABLE lt_ekpo FROM ekpo WHERE ebeln = lv_ebeln. LOOP AT lt_ekpo ASSIGNING . CONCATENATE -matnr -meins -werks INTO ls_bdcp_lines-tabkey RESPECTING BLANKS. APPEND ls_bdcp_lines TO ct_bdcp_lines. ENDLOOP. WHEN 'BUS2032'. " Sales Order lv_vbeln = iv_sender-instid. SELECT matnr meins werks INTO CORRESPONDING FIELDS OF TABLE lt_vbap FROM vbap WHERE vbeln = lv_vbeln. LOOP AT lt_vbap ASSIGNING . CONCATENATE -matnr -meins -werks INTO ls_bdcp_lines-tabkey RESPECTING BLANKS. APPEND ls_bdcp_lines TO ct_bdcp_lines. ENDLOOP. WHEN 'BUS2017'. " Goods Movement lv_mblnr = iv_sender-instid(10). SELECT matnr werks meins FROM mseg INTO CORRESPONDING FIELDS OF TABLE lt_mseg WHERE mblnr = lv_mblnr. LOOP AT lt_mseg ASSIGNING . CONCATENATE -matnr -meins -werks INTO ls_bdcp_lines-tabkey RESPECTING BLANKS. APPEND ls_bdcp_lines TO ct_bdcp_lines. ENDLOOP. WHEN 'BUS2093'. " Material Reservation lv_rsnum = iv_sender-instid. SELECT matnr werks meins FROM resb INTO CORRESPONDING FIELDS OF TABLE lt_resb WHERE rsnum = lv_rsnum. LOOP AT lt_resb ASSIGNING . CONCATENATE -matnr -meins -werks INTO ls_bdcp_lines-tabkey RESPECTING BLANKS. APPEND ls_bdcp_lines TO ct_bdcp_lines. ENDLOOP. WHEN 'LIKP'. " Outbound Delivery lv_vbeln = iv_sender-instid. SELECT matnr werks meins FROM lips INTO CORRESPONDING FIELDS OF TABLE lt_lips WHERE vbeln = lv_vbeln. LOOP AT lt_lips ASSIGNING . CONCATENATE -matnr -meins -werks INTO ls_bdcp_lines-tabkey RESPECTING BLANKS. APPEND ls_bdcp_lines TO ct_bdcp_lines. ENDLOOP. ENDCASE. CLEAR ls_bdcp_lines. ENDMETHOD.
Link the Business Objects that will trigger the ATP:
- Go to section Event Linkage
- Add New Entry and specify:
- Object Category: BOR Object Type
- Object Type: The Business Object Type sending the event
- Event: Event to react to
- Receiver Function Module: /ASADEV/ACI_EVENTS_TRIGGER
- Type linkage active: tick the checkbox
Object name | Object type | Event | TABLES | Transaction |
Sales Order | BUS2032 | Created, Changed | VBAK, VBAP | VA01, VA02 |
Purchase Order | BUS2012 | Created, Changed | EKKO, EKPO | ME21N, ME22n |
Delivery | LIKP | Created, Changed | LIKP, LIPS | VL01, VL02 |
Goods Movement | BUS2017 | Created | MKPF, MSEG | MB11 |
Material Reservation | ZBUS2093 | Created, Changed | RKPF, RESB | MB21, MB22 |
Test example
With the available trigger inside the Add-on a notification of the ATP will be sent as a JSON-File.
Payload structure:
{ "value": [ { "objectType": "BUS2012", "werks": "1200", "matnr": "DPC1002", "meins": "ST", "date": "20221011", "quantity": "4216.000 " }, { "objectType": "BUS2012", "werks": "1200", "matnr": "DPC1003", "meins": "ST", "date": "20221011", "quantity": "2063.000 " }, { "objectType": "BUS2012", "werks": "1200", "matnr": "DPC1004", "meins": "ST", "date": "20221011", "quantity": "1385.000 " }, { "objectType": "BUS2012", "werks": "1200", "matnr": "DPC1005", "meins": "ST", "date": "20221011", "quantity": "4886.000 " } ] }