Les BAPIs (Business Application Programming Interfaces) sont des interfaces standardisees pour l’acces aux objets metier SAP. Ils suivent des conventions strictes et permettent une integration uniforme.
Conventions BAPI
| Convention | Description |
|---|---|
| Nommage | BAPI_<OBJET>_<ACTION> |
| Parametre RETURN | Toujours BAPIRET2 ou BAPIRET2_T |
| Pas de COMMIT | L’appelant est responsable |
| Pas de dialogues | Pas de popups ou messages |
| Compatible RFC | Module fonction compatible RFC |
Structure BAPIRET2
| Champ | Description |
|---|---|
| TYPE | S/E/W/I/A (Success/Error/Warning/Info/Abort) |
| ID | Classe de message |
| NUMBER | Numero de message |
| MESSAGE | Texte de message complet |
| MESSAGE_V1-V4 | Variables |
| LOG_NO | Numero de log |
| LOG_MSG_NO | Numero de message du log |
Exemples
1. Appeler un BAPI standard
" BAPI pour lire un clientDATA: ls_address TYPE bapicustomer_04, lt_return TYPE TABLE OF bapiret2.
CALL FUNCTION 'BAPI_CUSTOMER_GETDETAIL2" EXPORTING customerno = '0000001000" IMPORTING customeraddress = ls_address TABLES return = lt_return.
" Verification des erreursIF line_exists( lt_return[ type = 'E' ] ). " Traiter les erreurs LOOP AT lt_return INTO DATA(ls_error) WHERE type = 'E'. WRITE: / ls_error-message. ENDLOOP.ELSE. " Succes WRITE: / ls_address-name, ls_address-city.ENDIF.2. BAPI avec COMMIT
DATA: lt_return TYPE TABLE OF bapiret2.
" Creer une commandeCALL FUNCTION 'BAPI_PO_CREATE1" EXPORTING poheader = ls_header poheaderx = ls_headerx TABLES poitem = lt_items poitemx = lt_itemsx return = lt_return.
" Verification des erreursREAD TABLE lt_return WITH KEY type = 'E' TRANSPORTING NO FIELDS.
IF sy-subrc <> 0. " Succes - effectuer le COMMIT CALL FUNCTION 'BAPI_TRANSACTION_COMMIT" EXPORTING wait = abap_true. " Attendre le commit
WRITE: / 'Commande creee'.ELSE. " Erreur - ROLLBACK CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
" Afficher les messages d'erreur LOOP AT lt_return INTO DATA(ls_msg) WHERE type CA 'EAX'. WRITE: / ls_msg-message. ENDLOOP.ENDIF.3. Creer son propre BAPI
" Module fonction : Z_BAPI_CUSTOMER_GETLISTFUNCTION z_bapi_customer_getlist.*"----------------------------------------------------------------------*"*"Interface locale :*" IMPORTING*" VALUE(IV_COUNTRY) TYPE LAND1 OPTIONAL*" VALUE(IV_MAX_ROWS) TYPE I DEFAULT 100*" EXPORTING*" VALUE(ET_CUSTOMERS) TYPE ZTT_CUSTOMER_LIST*" TABLES*" RETURN STRUCTURE BAPIRET2*"----------------------------------------------------------------------
" Validation des entrees IF iv_max_rows < 1 OR iv_max_rows > 10000. append_return( EXPORTING iv_type = 'E" iv_id = 'ZCUST" iv_number = '001" iv_v1 = CONV #( iv_max_rows ) CHANGING ct_return = return[] ). RETURN. ENDIF.
" Lire les donnees TRY. SELECT kunnr, name1, ort01, land1 FROM kna1 WHERE land1 = @iv_country OR @iv_country IS INITIAL INTO CORRESPONDING FIELDS OF TABLE @et_customers UP TO @iv_max_rows ROWS.
IF sy-subrc <> 0. append_return( EXPORTING iv_type = 'I" iv_id = 'ZCUST" iv_number = '002" CHANGING ct_return = return[] ). ELSE. append_return( EXPORTING iv_type = 'S" iv_id = 'ZCUST" iv_number = '003" iv_v1 = CONV #( lines( et_customers ) ) CHANGING ct_return = return[] ). ENDIF.
CATCH cx_root INTO DATA(lx_error). append_return( EXPORTING iv_type = 'E" iv_id = 'ZCUST" iv_number = '004" iv_v1 = lx_error->get_text( )(50) CHANGING ct_return = return[] ). ENDTRY.
ENDFUNCTION.
" Methode d'aide pour ajouter des entrees RETURNFORM append_return USING iv_type TYPE sy-msgty iv_id TYPE sy-msgid iv_number TYPE sy-msgno iv_v1 TYPE clike OPTIONAL iv_v2 TYPE clike OPTIONAL iv_v3 TYPE clike OPTIONAL iv_v4 TYPE clike OPTIONAL CHANGING ct_return TYPE bapiret2_t.
DATA: ls_return TYPE bapiret2, lv_text TYPE string.
MESSAGE ID iv_id TYPE iv_type NUMBER iv_number WITH iv_v1 iv_v2 iv_v3 iv_v4 INTO lv_text.
ls_return-type = iv_type. ls_return-id = iv_id. ls_return-number = iv_number. ls_return-message = lv_text. ls_return-message_v1 = iv_v1. ls_return-message_v2 = iv_v2. ls_return-message_v3 = iv_v3. ls_return-message_v4 = iv_v4.
APPEND ls_return TO ct_return.ENDFORM.4. Classe wrapper BAPI
CLASS zcl_customer_bapi DEFINITION. PUBLIC SECTION. TYPES: BEGIN OF ty_customer, kunnr TYPE kunnr, name1 TYPE name1_gp, ort01 TYPE ort01_gp, land1 TYPE land1_gp, END OF ty_customer, ty_customers TYPE STANDARD TABLE OF ty_customer WITH KEY kunnr.
METHODS: get_customer IMPORTING iv_kunnr TYPE kunnr RETURNING VALUE(rs_customer) TYPE ty_customer RAISING zcx_bapi_error.
METHODS: get_customers_by_country IMPORTING iv_country TYPE land1 RETURNING VALUE(rt_customers) TYPE ty_customers RAISING zcx_bapi_error.
METHODS: create_customer IMPORTING is_data TYPE ty_customer RETURNING VALUE(rv_kunnr) TYPE kunnr RAISING zcx_bapi_error.
PRIVATE SECTION. METHODS: check_return IMPORTING it_return TYPE bapiret2_t RAISING zcx_bapi_error.ENDCLASS.
CLASS zcl_customer_bapi IMPLEMENTATION. METHOD get_customer. DATA: ls_address TYPE bapicustomer_04, lt_return TYPE TABLE OF bapiret2.
CALL FUNCTION 'BAPI_CUSTOMER_GETDETAIL2" EXPORTING customerno = iv_kunnr IMPORTING customeraddress = ls_address TABLES return = lt_return.
check_return( lt_return ).
rs_customer = VALUE #( kunnr = iv_kunnr name1 = ls_address-name ort01 = ls_address-city land1 = ls_address-country ). ENDMETHOD.
METHOD get_customers_by_country. DATA: lt_address TYPE TABLE OF bapicustomer_04, lt_return TYPE TABLE OF bapiret2.
CALL FUNCTION 'BAPI_CUSTOMER_GETLIST" TABLES addressdata = lt_address return = lt_return.
check_return( lt_return ).
rt_customers = VALUE #( FOR ls_addr IN lt_address WHERE ( country = iv_country OR iv_country IS INITIAL ) ( kunnr = ls_addr-customer name1 = ls_addr-name ort01 = ls_addr-city land1 = ls_addr-country ) ). ENDMETHOD.
METHOD create_customer. DATA: lt_return TYPE TABLE OF bapiret2.
" BAPI pour creer... CALL FUNCTION 'BAPI_CUSTOMER_CREATE..." " Parametres... TABLES return = lt_return.
check_return( lt_return ).
" En cas de succes, COMMIT CALL FUNCTION 'BAPI_TRANSACTION_COMMIT" EXPORTING wait = abap_true.
rv_kunnr = '...'. " Nouveau numero client ENDMETHOD.
METHOD check_return. " Verifier les erreurs dans RETURN LOOP AT it_return INTO DATA(ls_return) WHERE type CA 'EAX'.
RAISE EXCEPTION TYPE zcx_bapi_error EXPORTING textid = zcx_bapi_error=>bapi_error msgid = ls_return-id msgno = ls_return-number msgv1 = ls_return-message_v1 msgv2 = ls_return-message_v2 msgv3 = ls_return-message_v3 msgv4 = ls_return-message_v4. ENDLOOP. ENDMETHOD.ENDCLASS.
" UtilisationTRY. DATA(lo_customer) = NEW zcl_customer_bapi( ). DATA(ls_customer) = lo_customer->get_customer( '0000001000' ).
WRITE: / ls_customer-name1, ls_customer-ort01.
CATCH zcx_bapi_error INTO DATA(lx_error). WRITE: / 'Erreur :', lx_error->get_text( ).ENDTRY.5. BAPI pour traitement de masse
FUNCTION z_bapi_orders_create_mass.*"----------------------------------------------------------------------*" IMPORTING*" VALUE(IT_ORDERS) TYPE ZTT_ORDER_CREATE*" EXPORTING*" VALUE(ET_SUCCESS) TYPE ZTT_ORDER_NUMBERS*" VALUE(ET_FAILED) TYPE ZTT_ORDER_FAILED*" TABLES*" RETURN STRUCTURE BAPIRET2*"----------------------------------------------------------------------
DATA: lt_order_return TYPE TABLE OF bapiret2, lv_order_no TYPE vbeln.
LOOP AT it_orders INTO DATA(ls_order). CLEAR: lt_order_return, lv_order_no.
" Creer une commande individuelle CALL FUNCTION 'BAPI_SALESORDER_CREATEFROMDAT2" EXPORTING order_header_in = ls_order-header IMPORTING salesdocument = lv_order_no TABLES return = lt_order_return order_items_in = ls_order-items order_partners = ls_order-partners.
" Verifier READ TABLE lt_order_return WITH KEY type = 'E' TRANSPORTING NO FIELDS.
IF sy-subrc <> 0 AND lv_order_no IS NOT INITIAL. " Succes CALL FUNCTION 'BAPI_TRANSACTION_COMMIT" EXPORTING wait = abap_true.
APPEND VALUE #( order_no = lv_order_no ) TO et_success.
APPEND VALUE #( type = 'S" id = 'ZORD" number = '001" message = |Commande { lv_order_no } creee| ) TO return. ELSE. " Erreur CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
APPEND VALUE #( index = sy-tabix messages = lt_order_return ) TO et_failed.
APPEND LINES OF lt_order_return TO return. ENDIF. ENDLOOP.
" Resume APPEND VALUE #( type = 'I" id = 'ZORD" number = '002" message = |{ lines( et_success ) } reussis, { lines( et_failed ) } echoues| ) TO return.
ENDFUNCTION.6. Classe d’exception BAPI
CLASS zcx_bapi_error DEFINITION INHERITING FROM cx_static_check CREATE PUBLIC.
PUBLIC SECTION. INTERFACES: if_t100_message.
CONSTANTS: BEGIN OF bapi_error, msgid TYPE symsgid VALUE 'ZBAPI', msgno TYPE symsgno VALUE '001', attr1 TYPE scx_attrname VALUE 'MSGV1', attr2 TYPE scx_attrname VALUE 'MSGV2', attr3 TYPE scx_attrname VALUE 'MSGV3', attr4 TYPE scx_attrname VALUE 'MSGV4', END OF bapi_error.
DATA: msgid TYPE sy-msgid, msgno TYPE sy-msgno, msgv1 TYPE sy-msgv1, msgv2 TYPE sy-msgv2, msgv3 TYPE sy-msgv3, msgv4 TYPE sy-msgv4.
METHODS: constructor IMPORTING textid LIKE if_t100_message=>t100key OPTIONAL previous LIKE previous OPTIONAL msgid TYPE sy-msgid OPTIONAL msgno TYPE sy-msgno OPTIONAL msgv1 TYPE sy-msgv1 OPTIONAL msgv2 TYPE sy-msgv2 OPTIONAL msgv3 TYPE sy-msgv3 OPTIONAL msgv4 TYPE sy-msgv4 OPTIONAL.
CLASS-METHODS: from_bapiret2 IMPORTING is_return TYPE bapiret2 RETURNING VALUE(ro_error) TYPE REF TO zcx_bapi_error.
CLASS-METHODS: from_bapiret2_table IMPORTING it_return TYPE bapiret2_t RETURNING VALUE(ro_error) TYPE REF TO zcx_bapi_error.ENDCLASS.
CLASS zcx_bapi_error IMPLEMENTATION. METHOD constructor. super->constructor( previous = previous ).
me->msgid = msgid. me->msgno = msgno. me->msgv1 = msgv1. me->msgv2 = msgv2. me->msgv3 = msgv3. me->msgv4 = msgv4.
IF textid IS INITIAL. if_t100_message~t100key = bapi_error. ELSE. if_t100_message~t100key = textid. ENDIF. ENDMETHOD.
METHOD from_bapiret2. ro_error = NEW #( msgid = is_return-id msgno = is_return-number msgv1 = is_return-message_v1 msgv2 = is_return-message_v2 msgv3 = is_return-message_v3 msgv4 = is_return-message_v4 ). ENDMETHOD.
METHOD from_bapiret2_table. " Utiliser le premier message d'erreur LOOP AT it_return INTO DATA(ls_return) WHERE type CA 'EAX'. ro_error = from_bapiret2( ls_return ). RETURN. ENDLOOP. ENDMETHOD.ENDCLASS.7. Appeler un BAPI via RFC
DATA: lt_return TYPE TABLE OF bapiret2.
" Destination RFCDATA(lv_destination) = 'PRD_CLNT100'.
CALL FUNCTION 'BAPI_CUSTOMER_GETLIST" DESTINATION lv_destination TABLES addressdata = lt_address return = lt_return EXCEPTIONS communication_failure = 1 MESSAGE lv_message system_failure = 2 MESSAGE lv_message OTHERS = 3.
IF sy-subrc <> 0. WRITE: / 'Erreur RFC :', lv_message.ELSE. " Verifier le retour BAPI check_return( lt_return ).ENDIF.8. BAPI avec Update Task
FUNCTION z_bapi_document_save.*"----------------------------------------------------------------------*" IMPORTING*" VALUE(IS_DOCUMENT) TYPE TY_DOCUMENT*" TABLES*" RETURN STRUCTURE BAPIRET2*"----------------------------------------------------------------------
" Validation perform_validation( EXPORTING is_document = is_document CHANGING ct_return = return[] ).
IF line_exists( return[ type = 'E' ] ). RETURN. ENDIF.
" Enregistrement dans Update Task CALL FUNCTION 'Z_UPDATE_DOCUMENT' IN UPDATE TASK EXPORTING is_document = is_document.
" Message de succes APPEND VALUE bapiret2( type = 'S" id = 'ZDOC" number = '001" message = 'Le document sera enregistre" ) TO return.
" Le COMMIT sera effectue par l'appelant !
ENDFUNCTION.9. Fonctions utilitaires BAPI
CLASS zcl_bapi_helper DEFINITION. PUBLIC SECTION. " Verifie si RETURN contient des erreurs CLASS-METHODS: has_errors IMPORTING it_return TYPE bapiret2_t RETURNING VALUE(rv_error) TYPE abap_bool.
" Filtre les messages par type CLASS-METHODS: get_messages_by_type IMPORTING it_return TYPE bapiret2_t iv_type TYPE sy-msgty RETURNING VALUE(rt_messages) TYPE bapiret2_t.
" Convertit RETURN en string CLASS-METHODS: return_to_string IMPORTING it_return TYPE bapiret2_t RETURNING VALUE(rv_string) TYPE string.
" Ajoute un message CLASS-METHODS: add_message IMPORTING iv_type TYPE sy-msgty iv_id TYPE sy-msgid iv_number TYPE sy-msgno iv_v1 TYPE clike OPTIONAL iv_v2 TYPE clike OPTIONAL iv_v3 TYPE clike OPTIONAL iv_v4 TYPE clike OPTIONAL CHANGING ct_return TYPE bapiret2_t.ENDCLASS.
CLASS zcl_bapi_helper IMPLEMENTATION. METHOD has_errors. rv_error = xsdbool( line_exists( it_return[ type = 'E' ] ) OR line_exists( it_return[ type = 'A' ] ) OR line_exists( it_return[ type = 'X' ] ) ). ENDMETHOD.
METHOD get_messages_by_type. rt_messages = FILTER #( it_return WHERE type = iv_type ). ENDMETHOD.
METHOD return_to_string. LOOP AT it_return INTO DATA(ls_return). IF rv_string IS NOT INITIAL. rv_string = rv_string && cl_abap_char_utilities=>newline. ENDIF. rv_string = rv_string && |{ ls_return-type }: { ls_return-message }|. ENDLOOP. ENDMETHOD.
METHOD add_message. DATA: ls_return TYPE bapiret2, lv_text TYPE string.
MESSAGE ID iv_id TYPE iv_type NUMBER iv_number WITH iv_v1 iv_v2 iv_v3 iv_v4 INTO lv_text.
ls_return = VALUE #( type = iv_type id = iv_id number = iv_number message = lv_text message_v1 = iv_v1 message_v2 = iv_v2 message_v3 = iv_v3 message_v4 = iv_v4 ).
APPEND ls_return TO ct_return. ENDMETHOD.ENDCLASS.
" UtilisationDATA: lt_return TYPE bapiret2_t.
zcl_bapi_helper=>add_message( EXPORTING iv_type = 'S" iv_id = 'ZMSG" iv_number = '001" iv_v1 = 'Succes" CHANGING ct_return = lt_return).
IF zcl_bapi_helper=>has_errors( lt_return ). DATA(lv_errors) = zcl_bapi_helper=>return_to_string( lt_return ). MESSAGE lv_errors TYPE 'E'.ENDIF.10. BAPI Explorer (BAPI)
Transaction : BAPI
1. Selectionner l'objet metier (par ex. Customer)2. Afficher les methodes (GetList, GetDetail, Create, etc.)3. Consulter la documentation et les parametres4. Determiner le nom du module fonction5. Possibilite de test via SE3711. BAPIs standard importants
" ClientsCALL FUNCTION 'BAPI_CUSTOMER_GETLIST'. " Lister les clientsCALL FUNCTION 'BAPI_CUSTOMER_GETDETAIL2'. " Details clientCALL FUNCTION 'BAPI_CUSTOMER_CREATEFROMDAT1'. " Creer un client
" FournisseursCALL FUNCTION 'BAPI_VENDOR_GETLIST'. " Lister les fournisseursCALL FUNCTION 'BAPI_VENDOR_GETDETAIL'. " Details fournisseur
" ArticlesCALL FUNCTION 'BAPI_MATERIAL_GETLIST'. " Lister les articlesCALL FUNCTION 'BAPI_MATERIAL_GET_DETAIL'. " Details article
" Commandes d'achatCALL FUNCTION 'BAPI_PO_CREATE1'. " Creer une commandeCALL FUNCTION 'BAPI_PO_CHANGE'. " Modifier une commandeCALL FUNCTION 'BAPI_PO_GETDETAIL'. " Details commande
" Commandes de venteCALL FUNCTION 'BAPI_SALESORDER_CREATEFROMDAT2'. " Creer une commandeCALL FUNCTION 'BAPI_SALESORDER_GETLIST'. " Lister les commandesCALL FUNCTION 'BAPI_SALESORDER_CHANGE'. " Modifier une commande
" EcrituresCALL FUNCTION 'BAPI_ACC_DOCUMENT_POST'. " Comptabiliser une piece FI
" Controle de transactionCALL FUNCTION 'BAPI_TRANSACTION_COMMIT'. " CommitCALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'. " RollbackChecklist BAPI
✓ Le module fonction est compatible RFC✓ Parametre RETURN de type BAPIRET2✓ Pas de COMMIT WORK dans le BAPI✓ Pas d'instructions MESSAGE✓ Pas d'appels de dialogue (popups)✓ Gestion complete des erreurs✓ Documentation des parametres✓ Controle d'autorisation implemente✓ Validation des entrees presente✓ Testable via SE37Remarques importantes / Bonnes pratiques
- COMMIT WORK jamais dans le BAPI - l’appelant decide.
- RETURN toujours rempli avec des messages explicites.
- Marquer comme compatible RFC pour les appels distants.
- Pas d’instructions MESSAGE - seulement remplir RETURN.
- Implementer le controle d’autorisation dans le BAPI.
- Validation des entrees avant le traitement.
- Classes wrapper pour une utilisation simplifiee.
- BAPI Explorer (transaction BAPI) pour la documentation.
- Traitement de masse avec COMMITs individuels par enregistrement.
- Combinez avec les Classes d’exception pour l’integration OO.