Tuesday, July 15, 2025

🛒Create Purchase Order using BAPI

To create a Purchase Order programmatically in SAP, we use the BAPI: BAPI_PO_CREATE1

This BAPI can be implemented in two ways:

  1. Custom ABAP Report - Write a program using SE38
  2. Direct Testing - Use SE37 (Function Builder) for testing


Method 1: Custom ABAP Report (SE38)

Complete Code Example

REPORT zpo_creation_using_bapi.

DATA: lt_poitem    TYPE TABLE OF bapimepoitem,
      lt_poitemx   TYPE TABLE OF bapimepoitemx,
      lt_return    TYPE TABLE OF bapiret2,
      ls_header    TYPE bapimepoheader,
      ls_headerx   TYPE bapimepoheaderx,
      lv_po_number TYPE bapivbeln.

START-OF-SELECTION.
  " Fill Header Data
  ls_header-doc_type = 'NB'.        " Standard PO
  ls_header-vendor = '1000'.        " Vendor Number
  ls_header-comp_code = '1000'.     " Company Code
  ls_header-purch_org = '1000'.     " Purchase Organization
  ls_header-pur_group = '001'.      " Purchase Group
  
  " Fill Header X-Structure (Change Indicators)
  ls_headerx-doc_type = 'X'.
  ls_headerx-vendor = 'X'.
  ls_headerx-comp_code = 'X'.
  ls_headerx-purch_org = 'X'.
  ls_headerx-pur_group = 'X'.
  
  " Fill Item Data
  APPEND VALUE #( po_item = '00010'
                  material = 'MAT001'
                  plant = '1000'
                  quantity = '10'
                  net_price = '50' ) TO lt_poitem.
  
  " Fill Item X-Structure (Change Indicators)
  APPEND VALUE #( po_item = '00010'
                  material = 'X'
                  plant = 'X'
                  quantity = 'X'
                  net_price = 'X' ) TO lt_poitemx.
  
  " Call BAPI to Create PO
  CALL FUNCTION 'BAPI_PO_CREATE1'
    EXPORTING
      poheader  = ls_header
      poheaderx = ls_headerx
    IMPORTING
      exppurchaseorder = lv_po_number
    TABLES
      return    = lt_return
      poitem    = lt_poitem
      poitemx   = lt_poitemx.
  
  " Commit the Transaction
  CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
    EXPORTING
      wait = 'X'.
  
  " Display Results
  IF lv_po_number IS NOT INITIAL.
    WRITE: / 'Purchase Order Created:', lv_po_number.
  ELSE.
    WRITE: / 'PO Creation Failed. Check return messages.'.
  ENDIF.

Key Data Structures

POHEADER (Header Data)

  • DOC_TYPE: Document type (e.g., 'NB' for Standard PO)
  • VENDOR: Vendor number
  • COMP_CODE: Company code
  • PURCH_ORG: Purchase organization
  • PUR_GROUP: Purchase group

POHEADERX (Header Change Indicators)

  • Mark fields with 'X' for data that should be processed
  • Must correspond to filled fields in POHEADER

POITEM (Item Data)

  • PO_ITEM: Item number (e.g., '00010')
  • MATERIAL: Material number
  • PLANT: Plant code
  • QUANTITY: Order quantity
  • NET_PRICE: Net price per unit

POITEMX (Item Change Indicators)

  • Mark fields with 'X' for data that should be processed
  • Must correspond to filled fields in POITEM


Method 2: Direct Testing using SE37

Step-by-Step Process with Visual Guide

Step 1: Access Function Builder

  1. Go to SE37 (Function Builder) or BAPI transaction
  2. Enter function module: BAPI_PO_CREATE1
  3. Click Test/Execute (F8)
┌─────────────────────────────────────────────────────────────┐
│ Function Builder: Initial Screen                            │
├─────────────────────────────────────────────────────────────┤
│ Function Module: BAPI_PO_CREATE1                            │
│                                                             │
│ [Test/Execute] [Display] [Change] [Create]                  │
└─────────────────────────────────────────────────────────────┘

Step 2: Fill Header Data (POHEADER)

Navigate to POHEADER and fill mandatory fields:

Screen Layout:

┌─────────────────────────────────────────────────────────────┐
│ Test Function Module: BAPI_PO_CREATE1                       │
├─────────────────────────────────────────────────────────────┤
│ Import Parameters:                                          │
│ ├─ POHEADER          [📁] <- Click to expand                |
│ ├─ POHEADERX         [📁]                                   │
│ ├─ POADDRVENDOR      [📁]                                   │
│ ├─ TESTRUN           [ ]                                    │
│                                                             │
│ Table Parameters:                                           │
│ ├─ POITEM            [📁]                                   │
│ ├─ POITEMX           [📁]                                   │
│ ├─ RETURN            [📁]                                   │
└─────────────────────────────────────────────────────────────┘

POHEADER Fields to Fill:

┌─────────────────────────────────────────────────────────────┐
│ Structure POHEADER                                          │
├─────────────────────────────────────────────────────────────┤
│ COMP_CODE    : 1000        (Company Code)                   │
│ DOC_TYPE     : NB          (Document Type)                  │
│ VENDOR       : 1000        (Vendor Number)                  │
│ PURCH_ORG    : 1000        (Purchase Organization)          │
│ PUR_GROUP    : 001         (Purchase Group)                 │
│ CURRENCY     : USD         (Currency)                       │
│ DOC_DATE     : 2024-01-15  (Document Date)                  │
└─────────────────────────────────────────────────────────────┘

Step 3: Set Header Indicators (POHEADERX)

Screen View:

┌─────────────────────────────────────────────────────────────┐
│ Structure POHEADERX                                         │
├─────────────────────────────────────────────────────────────┤
│ COMP_CODE    : X           (Mark fields to be processed)    │
│ DOC_TYPE     : X                                            │
│ VENDOR       : X                                            │
│ PURCH_ORG    : X                                            │
│ PUR_GROUP    : X                                            │
│ CURRENCY     : X                                            │
│ DOC_DATE     : X                                            │
└─────────────────────────────────────────────────────────────┘

Step 4: Fill Item Data (POITEM)

Table View:

┌────────────────────────────────────────────────────────────────────────────┐
│ Table POITEM                                                               │
├────────────────────────────────────────────────────────────────────────────┤
│ Row│PO_ITEM│MATERIAL│PLANT│STGE_LOC│QUANTITY│NET_PRICE│PRICE_UNIT│UNIT     │
├────┼───────┼────────┼─────┼────────┼────────┼─────────┼──────────┼──────── ┤
│  1 │ 00010 │ MAT001 │1000 │  0001  │   10   │   50.00 │    1     │   EA    │
│  2 │ 00020 │ MAT002 │1000 │  0001  │    5   │   75.00 │    1     │   EA    │
└────┴───────┴────────┴─────┴────────┴────────┴─────────┴──────────┴─────── -┘

Step 5: Set Item Indicators (POITEMX)

Table View:

┌────────────────────────────────────────────────────────────────────────────┐
│ Table POITEMX                                                              │
├────────────────────────────────────────────────────────────────────────────┤
│ Row│PO_ITEM│MATERIAL│PLANT│STGE_LOC│QUANTITY│NET_PRICE│PRICE_UNIT│UNIT     │
├────┼───────┼────────┼─────┼────────┼────────┼─────────┼──────────┼─────── ─┤
│  1 │ 00010 │   X    │  X  │   X    │   X    │    X    │    X     │   X     │
│  2 │ 00020 │   X    │  X  │   X    │   X    │    X    │    X     │   X     │
└────┴───────┴────────┴─────┴────────┴────────┴─────────┴──────────┴─────── ─┘

Step 6: Save Test Data

Save Dialog:

┌─────────────────────────────────────────────────────────────┐
│ Save Test Data                                              │
├─────────────────────────────────────────────────────────────┤
│ Test Data Name: PO_CREATE_TEST_001                          │
│ Description: Test data for PO creation                      │
│                                                             │
│ [Save] [Cancel]                                             │
└─────────────────────────────────────────────────────────────┘

Execution Process

Step 1: Setup Test Sequence

Navigation Path: SE37 → Function Module → Execute → Test Sequences

Test Sequence Setup Screen:

┌─────────────────────────────────────────────────────────────┐
│ Test Sequence Maintenance                                   │
├─────────────────────────────────────────────────────────────┤
│ Sequence Name: PO_CREATION_SEQUENCE                         │
│                                                             │
│ Function Modules in Sequence:                               │
│ ┌─────┬─────────────────────────────────────────────────────┐ │
│ │ No. │ Function Module                                     │ │
│ ├─────┼─────────────────────────────────────────────────────┤ │
│ │  1  │ BAPI_PO_CREATE1                                    │ │
│ │  2  │ BAPI_TRANSACTION_COMMIT                            │ │
│ └─────┴─────────────────────────────────────────────────────┘ │
│                                                             │
│ [Execute] [Save] [Test Data Directory]                      │
└─────────────────────────────────────────────────────────────┘

Step 2: Execute Test Sequence

Test Data Directory Screen:

┌─────────────────────────────────────────────────────────────┐
│ Test Data Directory                                         │
├─────────────────────────────────────────────────────────────┤
│ Available Test Data:                                        │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ ☑ PO_CREATE_TEST_001 - Test data for PO creation        │ │
│ │ ☐ PO_CREATE_TEST_002 - Alternative test data            │ │
│ │ ☐ PO_CREATE_TEST_003 - Vendor 2000 test data            │ │
│ └─────────────────────────────────────────────────────────┘ │
│                                                             │
│ [Execute] [Create] [Change] [Delete]                        │
└─────────────────────────────────────────────────────────────┘

Step 3: Execution Results

BAPI_PO_CREATE1 Results:

┌─────────────────────────────────────────────────────────────┐
│ Function Module Results: BAPI_PO_CREATE1                    │
├─────────────────────────────────────────────────────────────┤
│ Export Parameters:                                          │
│ EXPPURCHASEORDER: 4500000123                                │
│                                                             │
│ Return Messages:                                            │
│ ┌─────┬──────┬────────────────────────────────────────────┐ │
│ │Type │ ID   │ Message                                    │ │
│ ├─────┼──────┼────────────────────────────────────────────┤ │
│ │ S   │ ME   │ Purchase order 4500000123 created          │ │
│ │ S   │ ME   │ Item 00010 created                         │ │
│ │ S   │ ME   │ Item 00020 created                         │ │
│ └─────┴──────┴────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘

BAPI_TRANSACTION_COMMIT Results:

┌─────────────────────────────────────────────────────────────┐
│ Function Module Results: BAPI_TRANSACTION_COMMIT            │
├─────────────────────────────────────────────────────────────┤
│ Return Code: 000                                            │
│ Message: Transaction committed successfully                 │
│                                                             │
│ Status: ✓ Purchase Order 4500000123 committed to database   │
└─────────────────────────────────────────────────────────────┘

Step 4: Verification in ME23N

Display Purchase Order Screen:

┌─────────────────────────────────────────────────────────────┐
│ Display Purchase Order: 4500000123                          │
├─────────────────────────────────────────────────────────────┤
│ Header Data:                                                │
│ Vendor......: 1000        Doc Type.....: NB                 │
│ Company Code: 1000        Purch Org....: 1000               │
│ Created by..: USER001     Created on...: 15.01.2024         │
│                                                             │
│ Items:                                                      │
│ ┌─────┬────────┬─────┬────────┬─────────┬─────────────────┐ │
│ │Item │Material│Plant│Quantity│Net Price│      Amount     │ │
│ ├─────┼────────┼─────┼────────┼─────────┼─────────────────┤ │
│ │00010│ MAT001 │1000 │   10   │   50.00 │        500.00   │ │
│ │00020│ MAT002 │1000 │    5   │   75.00 │        375.00   │ │
│ └─────┴────────┴─────┴────────┴─────────┴─────────────────┘ │
│                                           Total: 875.00     │
└─────────────────────────────────────────────────────────────┘

Important Parameters Explained

Mandatory Header Fields

ls_header-comp_code = '1000'.     " Company Code
ls_header-doc_type = 'NB'.        " Document Type
ls_header-vendor = '1000'.        " Vendor Number
ls_header-purch_org = '1000'.     " Purchase Organization
ls_header-pur_group = '001'.      " Purchase Group

X-Structure Concept

The X-structures (POHEADERX, POITEMX) are change indicators:

  • 'X' = Field should be processed
  • ' ' = Field should be ignored

BAPI_TRANSACTION_COMMIT

Always call this function after BAPI_PO_CREATE1 to:

  • Commit the database transaction
  • Make changes permanent
  • Use WAIT = 'X' for synchronous processing

Error Handling and Troubleshooting

Return Message Analysis with Visual Examples

Success Scenario

┌─────────────────────────────────────────────────────────────┐
│ Return Messages Table                                       │
├─────────────────────────────────────────────────────────────┤
│ Type│ID │Number│Message                                     │
├─────┼───┼──────┼────────────────────────────────────────────┤
│  S  │ME │  022 │Purchase order 4500000123 created           │
│  S  │ME │  055 │Item 00010 created                          │
│  S  │ME │  055 │Item 00020 created                          │
└─────┴───┴──────┴────────────────────────────────────────────┘
✓ Status: SUCCESS - PO Created Successfully

Error Scenario

┌─────────────────────────────────────────────────────────────┐
│ Return Messages Table                                       │
├─────────────────────────────────────────────────────────────┤
│ Type│ID │Number│Message                                     │
├─────┼───┼──────┼────────────────────────────────────────────┤
│  E  │ME │  025 │Vendor 9999 does not exist                  │
│  E  │ME │  030 │Material MAT999 not found                   │
│  W  │ME │  010 │Purchase organization not assigned          │
└─────┴───┴──────┴────────────────────────────────────────────┘
✗ Status: ERROR - PO Creation Failed

Debug Screen Examples

BAPI Parameters Debug View

┌─────────────────────────────────────────────────────────────┐
│ Debugger: BAPI_PO_CREATE1 Parameters                        │
├─────────────────────────────────────────────────────────────┤
│ POHEADER Structure:                                         │
│ ├─ COMP_CODE    = '1000'                                    │
│ ├─ DOC_TYPE     = 'NB'                                      │
│ ├─ VENDOR       = '1000'                                    │
│ ├─ PURCH_ORG    = '1000'                                    │
│ └─ PUR_GROUP    = '001'                                     │
│                                                             │
│ POITEM Table (2 entries):                                   │
│ ├─ Entry 1: PO_ITEM='00010', MATERIAL='MAT001'              │
│ └─ Entry 2: PO_ITEM='00020', MATERIAL='MAT002'              │
└─────────────────────────────────────────────────────────────┘

Best Practices

1. Data Validation

" Validate vendor exists
SELECT SINGLE lifnr FROM lfa1 
  INTO @DATA(lv_vendor)
  WHERE lifnr = @ls_header-vendor.

IF sy-subrc <> 0.
  MESSAGE 'Vendor does not exist' TYPE 'E'.
ENDIF.

2. Number Range Handling

" Let SAP assign PO number automatically
" Don't fill ls_header-po_number unless specific number needed

3. Transaction Control

" Always use BAPI_TRANSACTION_COMMIT
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
  EXPORTING
    wait = 'X'.

" For error scenarios, use BAPI_TRANSACTION_ROLLBACK
IF error_occurred = abap_true.
  CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
ENDIF.

4. Multiple Items Handling

" Add multiple items
APPEND VALUE #( po_item = '00010' material = 'MAT001' 
                quantity = '10' net_price = '50' ) TO lt_poitem.
APPEND VALUE #( po_item = '00020' material = 'MAT002' 
                quantity = '5' net_price = '75' ) TO lt_poitem.

" Corresponding X-entries
APPEND VALUE #( po_item = '00010' material = 'X' 
                quantity = 'X' net_price = 'X' ) TO lt_poitemx.
APPEND VALUE #( po_item = '00020' material = 'X' 
                quantity = 'X' net_price = 'X' ) TO lt_poitemx.

Verification Steps

1. Check PO in Display Mode

  • Transaction: ME23N
  • Enter the created PO number
  • Verify all data is correctly populated

2. Database Verification

" Check EKKO table for header data
SELECT SINGLE * FROM ekko
  INTO @DATA(ls_ekko)
  WHERE ebeln = @lv_po_number.

" Check EKPO table for item data
SELECT * FROM ekpo
  INTO TABLE @DATA(lt_ekpo)
  WHERE ebeln = @lv_po_number.

Common Use Cases

  1. Mass PO Creation: Process multiple POs from Excel files
  2. Automated Ordering: Create POs based on stock levels
  3. Integration: Connect external systems to SAP
  4. Workflow Integration: Automatic PO creation in approval workflows

Troubleshooting Tips

Issue: PO Not Created

  • Check return messages in RETURN table
  • Verify all mandatory fields are filled
  • Ensure X-structures are properly set

Issue: Authorization Problems

  • Check user has authorization for PO creation
  • Verify company code and purchase organization access

Issue: Master Data Missing

  • Ensure vendor master exists (LFA1)
  • Verify material master exists (MARA)
  • Check plant and storage location setup

No comments:

Post a Comment