Late Numbering in SAP ABAP RAP

In SAP’s ABAP RESTful Application Programming (RAP) model, late numbering is a critical technique for managing unique identifiers like document numbers, order IDs, or transaction codes. Unlike traditional numbering that assigns keys before saving data, late numbering generates these identifiers after successful validation and persistence.

Why is Late Numbering Important?

  • Prevents number range gaps from failed transactions
  • Enables external system integration for key generation
  • Supports complex validation workflows
  • Improves data integrity in high-volume systems

How Late Numbering Works in RAP

1. Behavior Definition Setup

Enable late numbering in your behavior definition:

define behavior for ZRAP_SalesOrder
late numbering
{
  create;
  update;
  delete;
}

Key Components

  • DETERMINE ON SAVE: Triggers numbering after persistence
  • Number Range Objects: Configured via transaction SNRO
  • Exception Handling: Critical for duplicate key scenarios

Complete ABAP Implementation

Step 1: Behavior Definition

managed implementation in class ZBP_RAP_SALESORDER unique;
strict ( 2 );
with draft;

define behavior for ZRAP_SalesOrder
late numbering
{
  create;
  update;
  delete;
  field ( readonly ) SalesOrderNumber;
  determination generateSalesOrderNumber on save { create; }
}

Step 2: Behavior Implementation Class

CLASS zbp_rap_salesorder DEFINITION
  PUBLIC
  ABSTRACT
  FINAL
  FOR BEHAVIOR OF zrap_salesorder.

  PUBLIC SECTION.
  PRIVATE SECTION.
    METHODS generateSalesOrderNumber FOR DETERMINE ON SAVE
      IMPORTING keys FOR SalesOrder~generateSalesOrderNumber.
ENDCLASS.

CLASS zbp_rap_salesorder IMPLEMENTATION.
  METHOD generateSalesOrderNumber.
    " Read all sales orders without numbers
    READ ENTITIES OF zrap_salesorder IN LOCAL MODE
      ENTITY SalesOrder
        FIELDS ( SalesOrderUuid )
        WITH VALUE #( FOR key IN keys ( SalesOrderUuid = key-SalesOrderUuid ) )
      RESULT DATA(sales_orders).

    " Process numbering
    LOOP AT sales_orders ASSIGNING FIELD-SYMBOL(<so>) WHERE SalesOrderNumber IS INITIAL.
      TRY.
          " Get next number from range
          cl_numberrange_runtime=>number_get(
            EXPORTING
              nr_range_nr = '01'
              object      = 'ZSO_NUM'
            IMPORTING
              number      = DATA(lv_number) ).

          " Format number if needed
          <so>-SalesOrderNumber = |SO{ lv_number ALPHA = IN }|.

        CATCH cx_number_ranges INTO DATA(lx_error).
          " Log error
          APPEND VALUE #(
            SalesOrderUuid = <so>-SalesOrderUuid
            %msg = new_message(
              id       = 'ZSO_MSG'
              number   = '001'
              severity = if_abap_behv_message=>severity-error )
          ) TO reported-salesorder.
      ENDTRY.
    ENDLOOP.

    " Update entities with new numbers
    MODIFY ENTITIES OF zrap_salesorder IN LOCAL MODE
      ENTITY SalesOrder
        UPDATE FIELDS ( SalesOrderNumber )
        WITH VALUE #( FOR so IN sales_orders (
          SalesOrderUuid    = so-SalesOrderUuid
          SalesOrderNumber  = so-SalesOrderNumber
        ) ).
  ENDMETHOD.
ENDCLASS.

ABAP Class Handling Number Assignment

CLASS lhc_order DEFINITION INHERITING FROM cl_abap_behavior_handler.
  PRIVATE SECTION.
    METHODS get_instance_features FOR INSTANCE FEATURES
      IMPORTING keys REQUEST requested_features FOR order RESULT result.

    METHODS generate_order_number FOR DETERMINE ON SAVE
      IMPORTING keys FOR order~generate_order_number.
ENDCLASS.

CLASS lhc_order IMPLEMENTATION.
  METHOD generate_order_number.
    " Read all orders without numbers
    READ ENTITIES OF zrap_order IN LOCAL MODE
      ENTITY order
        FIELDS ( order_uuid )
        WITH VALUE #( FOR key IN keys ( order_uuid = key-order_uuid ) )
      RESULT DATA(orders).

    " Generate numbers for new orders
    LOOP AT orders ASSIGNING FIELD-SYMBOL(<order>) WHERE order_number IS INITIAL.
      " Call number range API
      TRY.
          cl_numberrange_runtime=>number_get(
            EXPORTING
              nr_range_nr = '01'
              object      = 'ZORDER'
            IMPORTING
              number      = DATA(lv_number) ).

          <order>-order_number = lv_number.
        CATCH cx_number_ranges INTO DATA(lx_error).
          " Handle error
      ENDTRY.
    ENDLOOP.

    " Update entities with new numbers
    MODIFY ENTITIES OF zrap_order IN LOCAL MODE
      ENTITY order
        UPDATE FIELDS ( order_number )
        WITH VALUE #( FOR order IN orders (
          order_uuid = order-order_uuid
          order_number = order-order_number
        ) ).
  ENDMETHOD.
ENDCLASS.

Best Practices for Implementation

  1. Number Range Configuration
    • Set up via SNRO with sufficient buffer size
    • Consider annual numbering if required
  2. Error Handling
    • Implement comprehensive logging
    • Use SAP messages for user feedback
  3. Performance Optimization
    • Use buffered number ranges for high-volume scenarios
    • Consider bulk number generation for mass operations
  4. Testing Strategy
    • Unit test numbering logic
    • Load test with concurrent users

Key Advantages

  1. Flexibility: Numbers assigned after all validations pass
  2. No Gaps: Prevents number range gaps from failed transactions
  3. External Integration: Allows external system to provide numbers

When to Use Late Numbering

  • Complex validation requirements
  • Integration with external numbering systems
  • High-volume transactions where numbering efficiency matters

Conclusion

Late numbering in SAP RAP provides a robust solution for managing unique identifiers in modern Fiori applications. By implementing the pattern shown above, developers can:

✔ Ensure data consistency
✔ Support complex business rules
✔ Enable integration scenarios
✔ Maintain clean number ranges

For production implementations, always include:

  • Comprehensive error handling
  • Performance testing
  • Proper documentation

Leave a Comment