Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
ceedee666
Active Contributor

A few weeks back I was debugging some issue with the status management of an order in SAP CRM. That was the first time that I noticed, that the general status management functionality is part of the core functionality of SAP Netweaver. As I like to use SAP standard whenever possible I was wondering whether it is possible to use the standard status management in custom development.

Status management in custom developments is a requirement I encountered regularly in the past. Most of the time I implemented a basic status management myself on the basis of some custom domain with numerical status values. This basic status management notable lagged most of the features the standard status management provides, like e.g.

  • the possibility to have different system and user status
  • the ability to have multiple system status active
  • or customizable and extendible status values.

Searching SDN I could only find little information regarding the standard status management. While there is a wiki page in the CRM area of the SDN wiki (Status Management - CRM - SCN Wiki) and a few threads on the topic (e.g. Integrating a Z Business Object with SAP Standard general status mangement?

with some very helpful comment by rdiger.plantiko) I couldn't find any complete example or tutorial on the topic. Therefore, I decided to create one myself. I this blog I'll provide a complete example consisting of creating a custom status object, customizing the status schema and finally using it in a simple example program.

Creating a custom status object

For the purpose of this blog I create a simple database table ZCD_D_STATUS_OBJ as an example business object. This table only contains the three field MANDT, OBJECT_ID and OBJECT_TEXT.

The first thing that is needed to create a new status object for this table is a new object type including the necessary control parameters in table TBO00. The control parameters basically specify in which database table the custom object is stored and which are the key fields identifying an entry. For this example I create an new object type "Z1" with the value "ZCD_D_STATUS_OBJ" for the fields "Table" and "Ref.Struc." and "OBJECT_ID" for the field "Key Field":

Next a new object type needs to be created using transaction BS12. For this example I created the object type ZT1. No further customizing is needed here for this example.

With this basic setup in place, it is now possible to customize the status schema for our new status object. Customizing the status schema is done via transaction BS12. I created a test status schema ZCDT0001 for this example. The status schema consists only of the following three status:

  • CREA - Created
  • PROC - Processes
  • FINI - Finished.

CREA is set as the initial status value. The lowest and highest status numbers are set up in such a way that it is always only possible to go to a higher status, e.g. from PROC to FINI.

Now all the customizing is in place to use the custom status object.

Test program for the custom status object

The function modules necessary to use the standard status management are locate in the function group BSVA in the package BSV. The following simple test program shows how to use these function modules to create and update the custom status object. The test program consists of the following parts:

  • First in lines 18-31 I simply use the BP number range to create an unique key for the entry in the custom table.
  • After that in lines 33-68 the custom status object for the object type ZT1 and the status schema ZCDT0001 is created.
  • In lines 70-98 the initial status values are read and printed to the output.
  • Finally in lines 100-163 some external and internal status values are set and then read and printed to the output again.


REPORT zcd_test_status_object.
TYPES: BEGIN OF object_key,
        object_id TYPE char10,
       END OF object_key.
DATA: status_test_obj TYPE zcd_d_status_obj,
      object_key TYPE object_key,
      status_obj_nr TYPE j_objnr,
      object_type   TYPE j_obtyp,
      status_schema TYPE j_stsma,
      status_number TYPE j_stonr,
      status_table  TYPE ttjstat,
      s             TYPE string.
FIELD-SYMBOLS: <status> TYPE jstat.
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"Initialize the object key with an unique value
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
CALL FUNCTION 'NUMBER_GET_NEXT'
  EXPORTING
    nr_range_nr = '01'
    object      = 'BU_PARTNER'
  IMPORTING
    number      = status_test_obj-object_id.
status_test_obj-object_text = 'Test Status Obj ' && status_test_obj-object_id.
INSERT zcd_d_status_obj FROM status_test_obj.
object_key-object_id = status_test_obj-object_id.
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"Creation of the status object
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
CALL FUNCTION 'OBJECT_NUMBER_GET_GENERIC'
  EXPORTING
    i_obart               = 'Z1'
    i_objectkey           = object_key
  IMPORTING
    e_objnr               = status_obj_nr
  EXCEPTIONS
    number_already_exists = 1
    obart_invalid         = 2
    objectkey_missing     = 3
    OTHERS                = 4.
IF sy-subrc <> 0.
  MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
              WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
CALL FUNCTION 'STATUS_OBJECT_CREATE'
  EXPORTING
    objnr                        = status_obj_nr
    obtyp                        = 'ZT1'
    stsma                        = 'ZCDT0001'
  EXCEPTIONS
    obtyp_invalid                = 1
    status_object_already_exists = 2
    stsma_invalid                = 3
    stsma_obtyp_invalid          = 4
    OTHERS                       = 5.
IF sy-subrc <> 0.
  MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
             WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
COMMIT WORK AND WAIT.
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"Read the initial status values and print it
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
CALL FUNCTION 'STATUS_READ'
  EXPORTING
    objnr            = status_obj_nr
  IMPORTING
    obtyp            = object_type
    stsma            = status_schema
    stonr            = status_number
  TABLES
    status           = status_table
  EXCEPTIONS
    object_not_found = 1
    OTHERS           = 2.
IF sy-subrc <> 0.
  MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
             WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
WRITE / 'Initial status values'.
s = |Object Type: | && object_type && | - Status Schema: | && status_schema && | - Status Number: | && status_number.
WRITE / s.
WRITE / 'Status Table:'.
LOOP AT status_table ASSIGNING <status>.
  s = |Status: | && <status>-stat && | - Inactive: | && <status>-inact.
  WRITE / s.
ENDLOOP.
ULINE.
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"Set some external and internal status values and print it
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
CALL FUNCTION 'STATUS_CHANGE_EXTERN'
  EXPORTING
    objnr               = status_obj_nr
    user_status         = 'E0003'
  EXCEPTIONS
    object_not_found    = 1
    status_inconsistent = 2
    status_not_allowed  = 3
    OTHERS              = 4.
IF sy-subrc <> 0.
  MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
             WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
CLEAR status_table.
APPEND INITIAL LINE TO status_table ASSIGNING <status>.
<status>-stat = 'I0098'.
CALL FUNCTION 'STATUS_CHANGE_INTERN'
  EXPORTING
    objnr               = status_obj_nr
  TABLES
    status              = status_table
  EXCEPTIONS
    object_not_found    = 1
    status_inconsistent = 2
    status_not_allowed  = 3
    OTHERS              = 4.
IF sy-subrc <> 0.
  MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
               WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
CLEAR status_table.
CALL FUNCTION 'STATUS_READ'
  EXPORTING
    objnr            = status_obj_nr   " Objektnummer
  IMPORTING
    obtyp            = object_type   " Objekttyp
    stsma            = status_schema    " Statusschema
    stonr            = status_number    " Statusordnungsnummer
  TABLES
    status           = status_table " Tabelle der Einzelstatus zum Objekt
  EXCEPTIONS
    object_not_found = 1
    OTHERS           = 2.
IF sy-subrc <> 0.
  MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
             WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
WRITE / 'New Status values'.
s = |Object Type: | && object_type && | - Status Schema: | && status_schema && | - Status Number: | && status_number.
WRITE / s.
WRITE / 'Status Table:'.
LOOP AT status_table ASSIGNING <status>.
  s = |Status: | && <status>-stat && | - Inactive: | && <status>-inact.
  WRITE / s.
ENDLOOP.
ULINE.


Running this program produces the following result:

After the status object has initially been created the user status E0001 is automatically set for the status object. This is the status that was defined in the status schema ZCDT0001. After setting the internal status I0098 and the user status E0003, the status E0001 is set to inactive.

I hope this blog provides an useful introduction for anyone trying to use the standard status management in a custom development.

Christian

7 Comments